Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 195774

Summary: [compiler][null][pattern] asymetry for potential nulls involving &&
Product: [Eclipse Project] JDT Reporter: Jeremy <eclipse.user>
Component: CoreAssignee: Ayushman Jain <amj87.iitr>
Status: CLOSED WONTFIX QA Contact:
Severity: minor    
Priority: P5    
Version: 3.3   
Target Milestone: ---   
Hardware: Macintosh   
OS: Mac OS X - Carbon (unsup.)   
Whiteboard: stalebug

Description Jeremy CLA 2007-07-08 17:26:21 EDT
The "detect potential null pointer access" option (set to warning) does not detect my potential null pointer accesses but does give a false positive.

The spurious null pointer access warning is reproducible with one code ordering but not with another.  See the difference between the "choose" method and the "equivalentChoose" method below.

Null pointer access warnings are missing where a class or instance field is accessed even when not necessarily initialized.

This test code differs from that in bug 179159 in a way which makes this code valid. :)

Expected: null pointer access warnings where "value" is accessed in "choose" and "equivalentChoose", and where "instanceValue" is accessed in "getValue".

Actual: the only null pointer access warning is a spurious one where "i" is accessed in "equivalentChoose".  That warning is spurious because of the two tests which combine to ensure that "i" cannot be null.

Apologies for my verbosity.  In the test code I wanted to ensure that the warnings and lack thereof were not side effects of my having turned on Javadoc warnings in Eclipse.

/**
 * shows spurious and absent NullPointerException warnings.
 */
public class NullPointerDiagnostic {
    
    /** @see #NullPointerDiagnostic() */
    static Integer value; // not initialized; could be null!
    
    /** @see #getValue() */
    Integer instanceValue; // not initialized
    
    /** @return a value */ 
    public int getValue() {
        return instanceValue.intValue(); // null pointer access warning expected but absent!
    }
    
    /** constructs an instance and initializes the class. */
    public NullPointerDiagnostic() {
        value = new Integer(0);
    }
    
    /**
     * returns the non{@code null} item of {@code i} or {@code j}.
     * If both are non{@code null}, returns a completely different object
     * instead.
     *  
     * @param i an {@link Integer} which may be {@code null}.
     * @param j an {@link Integer} which may be {@code null}.
     * @return the non{@code null} among {@code i} or {@code j}; 
     *         something else if both are non{@code null}.
     * @throws NullPointerException if both {@code i} and {@code j}
     *         are {@code null}.
     */
    public static int choose(Integer i, Integer j) {
        if ( i == null && j == null ) {
            throw new NullPointerException("At least one argument must be nonnull.");
        }
        if ( i == null ) {
            return j.intValue(); // no warning (as expected)
        }
        if ( j== null ) {
            return i.intValue();
        }
        return value.intValue(); // null pointer access warning expected but absent!
    }
    
    //however, interchange the order!
    
    /**
     * a different implementation of {@link #choose(Integer, Integer)}.
     * @param i as for {@link #choose(Integer, Integer)}
     * @param j as for {@link #choose(Integer, Integer)}
     * @return the same as {@link #choose(Integer, Integer)}
     * @throws NullPointerException as for {@link #choose(Integer, Integer)}
     */
    public static int equivalentChoose(Integer i, Integer j) {
        if ( i == null && j == null ) {
            throw new NullPointerException("At least one argument must be nonnull.");
        }
        if ( j== null ) {
            return i.intValue(); // spurious null pointer access warning!
        }
        if ( i == null ) {
            return j.intValue(); 
        }
        return value.intValue(); // null pointer access warning expected but absent!
    }
    
    /**
     * check that the code does behave the way I claim it does.
     * @param args the command line arguments. */
    public static void main(String[] args) {
        try {
            equivalentChoose(null, 3); // no NullPointerException
            System.out.println("Passed 1");
            equivalentChoose(3, null); // no NullPointerException
            System.out.println("Passed 2");
            choose(4,3); // NullPointerException, without warning!
        } catch ( NullPointerException e ) {
            e.printStackTrace(); // check the stacktrace; fails at value.intValue()
        }
        new NullPointerDiagnostic().getValue(); // throws, without warning!
    }

}
Comment 1 Maxime Daniel CLA 2007-07-09 02:34:38 EDT
As far as fields are concerned, we currently have no plans to support them.

Reproduced with 3.3 for i an j swap between choose and equivalentChoose, will investigate.

Updated the summary to reflect the case I'll tackle.
Comment 2 Maxime Daniel CLA 2007-07-10 05:56:01 EDT
Added test cases NullReferenceTest#86 and 87.
Comment 3 Maxime Daniel CLA 2007-07-10 06:49:11 EDT
We do not handle variables correlation so far. Accordingly, the spurious warning in equivalentChoose is incorrect but expected. The no warning in choose comes from the fact that another limitation strikes: we do not see j as tainted, because our encoding of null status makes no difference between tainted and potential null.

The net result is that:
- the observed misbehavior will be fixed if we decide at some point in time to invest in specific variables correlation patterns (variables correlation in general is out of scope); I'll tag the bug accordingly;
- I won't spend more time to align the 'good behavior' to the same misbehavior for the sole sake of consistency; if at a future time we decide to recode, then the misbehavior will probably show up, with the same treatment as the other one (i.e., treat with pattern if decided so).
Comment 4 Eclipse Webmaster CLA 2007-07-29 09:23:22 EDT
Changing OS from Mac OS to Mac OS X as per bug 185991
Comment 5 Eclipse Genie CLA 2020-01-25 15:27:03 EST
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. As such, we're closing this bug.

If you have further information on the current state of the bug, please add it and reopen this bug. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.