diff --git a/subst.c b/subst.c
index fc00cab0..f8983714 100644
--- a/subst.c
+++ b/subst.c
@@ -323,7 +323,7 @@ static WORD_DESC *parameter_brace_expand_word __P((char *, int, int, int, arrayi
 static char *parameter_brace_find_indir __P((char *, int, int, int));
 static WORD_DESC *parameter_brace_expand_indir __P((char *, int, int, int *, int *));
 static WORD_DESC *parameter_brace_expand_rhs __P((char *, char *, int, int, int, int *, int *));
-static void parameter_brace_expand_error __P((char *, char *));
+static void parameter_brace_expand_error __P((char *, char *, int));
 
 static int valid_length_expression __P((char *));
 static intmax_t parameter_brace_expand_length __P((char *));
@@ -6849,8 +6849,9 @@ parameter_brace_expand_rhs (name, value, c, quoted, pflags, qdollaratp, hasdolla
    used as the error message to print, otherwise a standard message is
    printed. */
 static void
-parameter_brace_expand_error (name, value)
+parameter_brace_expand_error (name, value, check_nullness)
      char *name, *value;
+     int check_nullness;
 {
   WORD_LIST *l;
   char *temp;
@@ -6865,7 +6866,12 @@ parameter_brace_expand_error (name, value)
       dispose_words (l);
     }
   else
-    report_error (_("%s: parameter null or not set"), name);
+    {
+      if (check_nullness)
+          report_error (_("%s: parameter null or not set"), name);
+      else
+          report_error (_("%s: parameter is not set"), name);
+    }
 
   /* Free the data we have allocated during this expansion, since we
      are about to longjmp out. */
@@ -8468,7 +8474,7 @@ bad_substitution:
 	    }
 	  else if (c == '?')
 	    {
-	      parameter_brace_expand_error (name, value);
+	      parameter_brace_expand_error (name, value, check_nullness);
 	      return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
 	    }
 	  else if (c != '+')
diff --git a/tests/modifier.right b/tests/modifier.right
new file mode 100644
index 00000000..4728f1af
--- /dev/null
+++ b/tests/modifier.right
@@ -0,0 +1,54 @@
+
+===== Modifier ? with X=_Unset
+OK
+
+===== Modifier ? with X=_Empty
+OK
+
+===== Modifier ? with X=something
+OK
+
+===== Modifier ?msg with X=_Unset
+OK
+
+===== Modifier ?msg with X=_Empty
+OK
+
+===== Modifier ?msg with X=something
+OK
+
+===== Modifier :? with X=_Unset
+OK
+
+===== Modifier :? with X=_Empty
+OK
+
+===== Modifier :? with X=something
+OK
+
+===== Modifier :?msg with X=_Unset
+OK
+
+===== Modifier :?msg with X=_Empty
+OK
+
+===== Modifier :?msg with X=something
+OK
+
+===== Modifier -defval with X=_Unset
+OK
+
+===== Modifier -defval with X=_Empty
+OK
+
+===== Modifier -defval with X=something
+OK
+
+===== Modifier :-defval with X=_Unset
+OK
+
+===== Modifier :-defval with X=_Empty
+OK
+
+===== Modifier :-defval with X=something
+OK
diff --git a/tests/modifier.tests b/tests/modifier.tests
new file mode 100755
index 00000000..102d7967
--- /dev/null
+++ b/tests/modifier.tests
@@ -0,0 +1,139 @@
+#
+# exercise some of the shell variable modifiers.
+# this script does not yield a meaningful exit status.
+# the caller is expected to check the overall output
+# against known good output.
+#
+
+# print a description of the test with the given args.
+TestHeader()
+{
+	local func=$1 var=$2 mod=$3 val=$4
+
+	echo ""
+	echo "===== Modifier $mod with $var=$val"
+}
+
+#
+# run the given test, compare output and status with expected.
+# Arguments:
+#	- exp_out - expected output
+#	- exp_stat - expected return status
+#	- remaining args are cmd to run, including TestHelper function
+# returns 1 if output or status does not match.
+#
+Checker()
+{
+	local exp_out=$1; shift
+	local exp_stat=$1; shift
+	local out stat failed
+
+	TestHeader "$@"
+
+	out=$("$@" 2>&1)
+	stat=$?
+
+	#
+	# canonicalize the output and status to facilitate comparison:
+	#	- if the output starts with "bash: ", remove it.
+	# 	- any non-zero status is replaced with _Error.
+	#
+	out=${out#*bash: }
+	if ((stat != 0)); then
+		stat=_Error
+	fi
+
+	# compare expected out and status
+	if [[ "$exp_out" != "$out" ]]; then
+		echo "Error: output expected=[$exp_out] actual=[$out]"
+		failed=1
+	fi
+	if [[ "$exp_stat" != "$stat" ]]; then
+		echo "Error: status expected=[$exp_stat] actual=[$stat]"
+		failed=1
+	fi
+	if ((failed)); then
+		return 1
+	fi
+	echo "OK"
+}
+
+#
+# print the bash statement to assign or unassign the given
+# variable to the given value.
+#
+# the special value _Unset causes the variable to be unset.
+# the special value _Empty is replaced with the empty string.
+#
+Assigner()
+{
+	local var=$1 val=$2
+	# assigner will be the pre-evaluation assignment.
+	case "$val" in
+	_Unset) echo "unset $var" ;;
+	_Empty) echo "$var=" ;;
+	*) echo "$var=$val" ;;
+	esac
+}
+
+# set the given variable as specified, and echo it with the given modifier.
+TestHelper()
+{
+	local var=$1 mod=$2 val=$3
+	local ass=$(Assigner "$var" "$val")
+
+	"${THIS_SH}" -c "$ass; echo \${$var$mod}" 2>&1
+
+	return "${PIPESTATUS[0]}"
+}
+
+# ----- start of mainline code
+VAR=X        # name of variable to use for testing
+
+# check the ? modifier on different values
+Checker "$VAR: parameter is not set" _Error \
+	TestHelper "$VAR" "?" _Unset
+Checker ""  0 \
+	TestHelper "$VAR" "?" _Empty
+Checker something 0 \
+	TestHelper "$VAR" "?" something
+
+# check the ?msg modifier on different values
+Checker "$VAR: msg" _Error \
+	TestHelper "$VAR" "?msg" _Unset
+Checker "" 0 \
+	TestHelper "$VAR" "?msg" _Empty
+Checker something 0 \
+	TestHelper "$VAR" "?msg" something
+
+# check the :? modifier on different values
+Checker "$VAR: parameter null or not set" _Error \
+	TestHelper "$VAR" ":?" _Unset
+Checker "$VAR: parameter null or not set" _Error \
+	TestHelper "$VAR" ":?" _Empty
+Checker something 0 \
+	TestHelper "$VAR" ":?" something
+
+# check the :?msg modifier on different values
+Checker "$VAR: msg" _Error \
+	TestHelper "$VAR" ":?msg" _Unset
+Checker "$VAR: msg" _Error \
+	TestHelper "$VAR" ":?msg" _Empty
+Checker something 0 \
+	TestHelper "$VAR" ":?msg" something
+
+# check the - modifier on different values.
+Checker defval 0 \
+	TestHelper "$VAR" "-defval" _Unset
+Checker "" 0 \
+	TestHelper "$VAR" "-defval" _Empty
+Checker something 0 \
+	TestHelper "$VAR" "-defval" something
+
+# check the :- modifier on different values
+Checker defval 0 \
+	TestHelper "$VAR" ":-defval" _Unset
+Checker defval 0 \
+	TestHelper "$VAR" ":-defval" _Empty
+Checker something 0 \
+	TestHelper "$VAR" ":-defval" something
diff --git a/tests/run-modifier b/tests/run-modifier
new file mode 100755
index 00000000..11ecacca
--- /dev/null
+++ b/tests/run-modifier
@@ -0,0 +1,2 @@
+${THIS_SH} ./modifier.tests > ${BASH_TSTOUT} 2>&1
+diff ${BASH_TSTOUT} modifier.right && rm -f ${BASH_TSTOUT}
