Index: src/test/org/apache/lucene/queryParser/TestQueryParser.java
===================================================================
--- src/test/org/apache/lucene/queryParser/TestQueryParser.java	(revision 909391)
+++ src/test/org/apache/lucene/queryParser/TestQueryParser.java	(working copy)
@@ -403,17 +403,24 @@
     } catch(ParseException pe) {
       // expected exception
     }
+    // as of 3.1, leading ? is allowed
+    assertWildcardQueryEquals("?Term", true, "?term");
+    // Test suffix queries: then allow
+    assertWildcardQueryEquals("*Term", true, "*term", true);
+    assertWildcardQueryEquals("?Term", true, "?term", true);
+  }
+  
+  /* @deprecated Remove in Lucene 4.0 */
+  @Deprecated
+  public void testWildcardBackCompat() throws Exception {
+    QueryParser qp = new QueryParser(Version.LUCENE_30, "bogus", new KeywordAnalyzer());
     try {
-      assertWildcardQueryEquals("?Term", true, "?term");
+      qp.parse("?Term");
       fail();
     } catch(ParseException pe) {
       // expected exception
     }
-    // Test suffix queries: then allow
-    assertWildcardQueryEquals("*Term", true, "*term", true);
-    assertWildcardQueryEquals("?Term", true, "?term", true);
   }
-  
   public void testLeadingWildcardType() throws Exception {
     QueryParser qp = getParser(null);
     qp.setAllowLeadingWildcard(true);
Index: src/java/org/apache/lucene/queryParser/QueryParser.java
===================================================================
--- src/java/org/apache/lucene/queryParser/QueryParser.java	(revision 909391)
+++ src/java/org/apache/lucene/queryParser/QueryParser.java	(working copy)
@@ -105,6 +105,8 @@
  * <p><b>NOTE</b>: You must specify the required {@link Version}
  * compatibility when creating QueryParser:
  * <ul>
+ *    <li> As of 3.1, only a leading * is considered a leading wildcard
+ *         by {@link #setAllowLeadingWildcard}.
  *    <li> As of 2.9, {@link #setEnablePositionIncrements} is true by
  *         default.
  * </ul>
@@ -155,8 +157,10 @@
    */
   static public enum Operator { OR, AND }
 
+  private Version matchVersion;
+
   /** Constructs a query parser.
-   *  @param matchVersion  Lucene version to match.  See <a href="#version">above</a>)
+   *  @param matchVersion  Lucene version to match.  See {@link <a href="#version">above</a>)
    *  @param f  the default field for query terms.
    *  @param a   used to find terms in the query text.
    */
@@ -164,6 +168,7 @@
     this(new FastCharStream(new StringReader("")));
     analyzer = a;
     field = f;
+    this.matchVersion = matchVersion;
     if (matchVersion.onOrAfter(Version.LUCENE_29)) {
       enablePositionIncrements = true;
     } else {
@@ -264,7 +269,7 @@
   /**
    * Set to <code>true</code> to allow leading wildcard characters.
    * <p>
-   * When set, <code>*</code> or <code>?</code> are allowed as 
+   * When set, <code>*</code> is allowed as 
    * the first character of a PrefixQuery and WildcardQuery.
    * Note that this can produce very slow
    * queries on big indexes. 
@@ -919,8 +924,11 @@
     if ("*".equals(field)) {
       if ("*".equals(termStr)) return newMatchAllDocsQuery();
     }
-    if (!allowLeadingWildcard && (termStr.startsWith("*") || termStr.startsWith("?")))
-      throw new ParseException("'*' or '?' not allowed as first character in WildcardQuery");
+    if (!allowLeadingWildcard && termStr.startsWith("*"))
+      throw new ParseException("'*' not allowed as first character in WildcardQuery");
+    if (!allowLeadingWildcard && !matchVersion.onOrAfter(Version.LUCENE_31)
+        && termStr.startsWith("?"))
+      throw new ParseException("'?' not allowed as first character in WildcardQuery");
     if (lowercaseExpandedTerms) {
       termStr = termStr.toLowerCase();
     }
@@ -1528,6 +1536,12 @@
     finally { jj_save(0, xla); }
   }
 
+  private boolean jj_3R_3() {
+    if (jj_scan_token(STAR)) return true;
+    if (jj_scan_token(COLON)) return true;
+    return false;
+  }
+
   private boolean jj_3R_2() {
     if (jj_scan_token(TERM)) return true;
     if (jj_scan_token(COLON)) return true;
@@ -1544,12 +1558,6 @@
     return false;
   }
 
-  private boolean jj_3R_3() {
-    if (jj_scan_token(STAR)) return true;
-    if (jj_scan_token(COLON)) return true;
-    return false;
-  }
-
   /** Generated Token Manager. */
   public QueryParserTokenManager token_source;
   /** Current token. */
Index: src/java/org/apache/lucene/queryParser/QueryParser.jj
===================================================================
--- src/java/org/apache/lucene/queryParser/QueryParser.jj	(revision 909391)
+++ src/java/org/apache/lucene/queryParser/QueryParser.jj	(working copy)
@@ -129,6 +129,8 @@
  * <p><b>NOTE</b>: You must specify the required {@link Version}
  * compatibility when creating QueryParser:
  * <ul>
+ *    <li> As of 3.1, only a leading * is considered a leading wildcard
+ *         by {@link #setAllowLeadingWildcard}.
  *    <li> As of 2.9, {@link #setEnablePositionIncrements} is true by
  *         default.
  * </ul>
@@ -179,6 +181,8 @@
    */
   static public enum Operator { OR, AND }
 
+  private Version matchVersion;
+
   /** Constructs a query parser.
    *  @param matchVersion  Lucene version to match.  See {@link <a href="#version">above</a>)
    *  @param f  the default field for query terms.
@@ -188,6 +192,7 @@
     this(new FastCharStream(new StringReader("")));
     analyzer = a;
     field = f;
+    this.matchVersion = matchVersion;
     if (matchVersion.onOrAfter(Version.LUCENE_29)) {
       enablePositionIncrements = true;
     } else {
@@ -288,7 +293,7 @@
   /**
    * Set to <code>true</code> to allow leading wildcard characters.
    * <p>
-   * When set, <code>*</code> or <code>?</code> are allowed as 
+   * When set, <code>*</code> is allowed as 
    * the first character of a PrefixQuery and WildcardQuery.
    * Note that this can produce very slow
    * queries on big indexes. 
@@ -943,8 +948,11 @@
     if ("*".equals(field)) {
       if ("*".equals(termStr)) return newMatchAllDocsQuery();
     }
-    if (!allowLeadingWildcard && (termStr.startsWith("*") || termStr.startsWith("?")))
-      throw new ParseException("'*' or '?' not allowed as first character in WildcardQuery");
+    if (!allowLeadingWildcard && termStr.startsWith("*"))
+      throw new ParseException("'*' not allowed as first character in WildcardQuery");
+    if (!allowLeadingWildcard && !matchVersion.onOrAfter(Version.LUCENE_31) 
+        && termStr.startsWith("?"))
+      throw new ParseException("'?' not allowed as first character in WildcardQuery");
     if (lowercaseExpandedTerms) {
       termStr = termStr.toLowerCase();
     }
Index: contrib/queryparser/src/test/org/apache/lucene/queryParser/standard/TestQPHelper.java
===================================================================
--- contrib/queryparser/src/test/org/apache/lucene/queryParser/standard/TestQPHelper.java	(revision 909391)
+++ contrib/queryparser/src/test/org/apache/lucene/queryParser/standard/TestQPHelper.java	(working copy)
@@ -499,12 +499,8 @@
     } catch (QueryNodeException pe) {
       // expected exception
     }
-    try {
-      assertWildcardQueryEquals("?Term", true, "?term");
-      fail();
-    } catch (QueryNodeException pe) {
-      // expected exception
-    }
+    // as of 3.1, leading ? is allowed
+    assertWildcardQueryEquals("?Term", true, "?term");
     // Test suffix queries: then allow
     assertWildcardQueryEquals("*Term", true, "*term", true);
     assertWildcardQueryEquals("?Term", true, "?term", true);
Index: contrib/queryparser/src/test/org/apache/lucene/queryParser/standard/TestQueryParserWrapper.java
===================================================================
--- contrib/queryparser/src/test/org/apache/lucene/queryParser/standard/TestQueryParserWrapper.java	(revision 909391)
+++ contrib/queryparser/src/test/org/apache/lucene/queryParser/standard/TestQueryParserWrapper.java	(working copy)
@@ -496,12 +496,8 @@
     } catch (ParseException pe) {
       // expected exception
     }
-    try {
-      assertWildcardQueryEquals("?Term", true, "?term");
-      fail();
-    } catch (ParseException pe) {
-      // expected exception
-    }
+    // as of 3.1, leading ? is allowed
+    assertWildcardQueryEquals("?Term", true, "?term");
     // Test suffix queries: then allow
     assertWildcardQueryEquals("*Term", true, "*term", true);
     assertWildcardQueryEquals("?Term", true, "?term", true);
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/standard/processors/AllowLeadingWildcardProcessor.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/standard/processors/AllowLeadingWildcardProcessor.java	(revision 909391)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/standard/processors/AllowLeadingWildcardProcessor.java	(working copy)
@@ -74,7 +74,6 @@
         
         switch (wildcardNode.getText().charAt(0)) {    
           case '*':
-          case '?':
             throw new QueryNodeException(new MessageImpl(
                 QueryParserMessages.LEADING_WILDCARD_NOT_ALLOWED, node
                     .toQueryString(new EscapeQuerySyntaxImpl())));    
