View | Details | Raw Unified | Return to bug 365983
Collapse All | Expand All

(-)a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java (-1 / +104 lines)
Lines 19-24 Link Here
19
import org.eclipse.core.runtime.FileLocator;
19
import org.eclipse.core.runtime.FileLocator;
20
import org.eclipse.core.runtime.Platform;
20
import org.eclipse.core.runtime.Platform;
21
import org.eclipse.jdt.core.JavaCore;
21
import org.eclipse.jdt.core.JavaCore;
22
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
22
23
23
// see bug 186342 - [compiler][null] Using annotations for null checking
24
// see bug 186342 - [compiler][null] Using annotations for null checking
24
public class NullAnnotationTest extends AbstractComparableTest {
25
public class NullAnnotationTest extends AbstractComparableTest {
Lines 52-58 Link Here
52
// Static initializer to specify tests subset using TESTS_* static variables
53
// Static initializer to specify tests subset using TESTS_* static variables
53
// All specified tests which do not belong to the class are skipped...
54
// All specified tests which do not belong to the class are skipped...
54
static {
55
static {
55
//		TESTS_NAMES = new String[] { "test_assignment_expression_1" };
56
//		TESTS_NAMES = new String[] { "test_nonnull_parameter_015" };
56
//		TESTS_NUMBERS = new int[] { 561 };
57
//		TESTS_NUMBERS = new int[] { 561 };
57
//		TESTS_RANGE = new int[] { 1, 2049 };
58
//		TESTS_RANGE = new int[] { 1, 2049 };
58
}
59
}
Lines 550-555 Link Here
550
		"Type mismatch: required \'@NonNull Object\' but the provided value is null\n" + 
551
		"Type mismatch: required \'@NonNull Object\' but the provided value is null\n" + 
551
		"----------\n");
552
		"----------\n");
552
}
553
}
554
// non-null varargs (message send)
555
public void test_nonnull_parameter_015() {
556
	runNegativeTest(
557
		new String[] {
558
			"X.java",
559
			"import org.eclipse.jdt.annotation.*;\n" +
560
			"public class X {\n" +
561
			"    void foo(@NonNull Object ... o) {\n" +
562
			"        if (o != null)\n" +
563
			"              System.out.print(o.toString());\n" +
564
			"    }\n" +
565
			"    void foo2(int i, @NonNull Object ... o) {\n" +
566
			"        if (o.length > 0 && o[0] != null)\n" +
567
			"              System.out.print(o[0].toString());\n" +
568
			"    }\n" +
569
			"    void bar() {\n" +
570
			"        foo((Object)null);\n" +		// unchecked: single plain argument
571
			"        Object[] objs = null;\n" +
572
			"        foo(objs);\n" +				// error
573
			"        foo(this, null);\n" +			// unchecked: multiple plain arguments
574
			"        foo2(2, (Object)null);\n" +    // unchecked: single plain argument
575
			"        foo2(2, null, this);\n" +      // unchecked: multiple plain arguments
576
			"        foo2(2, null);\n" +  			// error
577
			"    }\n" +
578
			"}\n"},
579
			"----------\n" + 
580
			"1. ERROR in X.java (at line 4)\n" + 
581
			"	if (o != null)\n" + 
582
			"	    ^\n" + 
583
			"Redundant null check: The variable o cannot be null at this location\n" + 
584
			"----------\n" + 
585
			"2. ERROR in X.java (at line 14)\n" + 
586
			"	foo(objs);\n" + 
587
			"	    ^^^^\n" + 
588
			"Type mismatch: required \'@NonNull Object[]\' but the provided value is null\n" + 
589
			"----------\n" + 
590
			"3. WARNING in X.java (at line 18)\n" + 
591
			"	foo2(2, null);\n" + 
592
			"	^^^^^^^^^^^^^\n" + 
593
			"The argument of type null should explicitly be cast to Object[] for the invocation of the varargs method foo2(int, Object...) from type X. It could alternatively be cast to Object for a varargs invocation\n" + 
594
			"----------\n" + 
595
			"4. ERROR in X.java (at line 18)\n" + 
596
			"	foo2(2, null);\n" + 
597
			"	        ^^^^\n" + 
598
			"Type mismatch: required \'@NonNull Object[]\' but the provided value is null\n" + 
599
			"----------\n",
600
		this.LIBS,
601
		true /* shouldFlush*/);
602
}
603
// non-null varargs (allocation and explicit constructor calls)
604
public void test_nonnull_parameter_016() {
605
	runNegativeTest(
606
		new String[] {
607
			"X.java",
608
			"import org.eclipse.jdt.annotation.*;\n" +
609
			"public class X {\n" +
610
			"    X(@NonNull Object ... o) {\n" +
611
			"        if (o != null)\n" +
612
			"              System.out.print(o.toString());\n" +
613
			"    }\n" +
614
			"    class Y extends X {\n" +
615
			"        Y(int i, @NonNull Object ... o) {\n" +
616
			"        	super(i, (Object)null);\n" +
617
			"        }\n" +
618
			"        Y(char c, @NonNull Object ... o) {\n" +
619
			"        	this(1, new Object(), null);\n" +
620
			"        }\n" +
621
			"    }\n" +
622
			"    void bar() {\n" +
623
			"        new X((Object[])null);\n" +
624
			"        new X(this, null);\n" +
625
			"        X x = new X(null, this);\n" +
626
			"        x.new Y(2, (Object)null);\n" +
627
			"        this.new Y(2, null, this);\n" +
628
			"        this.new Y(2, (Object[])null);\n" +
629
			"    }\n" +
630
			"}\n"},
631
			"----------\n" +
632
			"1. ERROR in X.java (at line 4)\n" +
633
			"	if (o != null)\n" +
634
			"	    ^\n" +
635
			"Redundant null check: The variable o cannot be null at this location\n" +
636
			"----------\n" +
637
			"2. ERROR in X.java (at line 16)\n" +
638
			"	new X((Object[])null);\n" +
639
			"	      ^^^^^^^^^^^^^^\n" +
640
			"Type mismatch: required \'@NonNull Object[]\' but the provided value is null\n" +
641
			"----------\n" +
642
			"3. ERROR in X.java (at line 21)\n" +
643
			"	this.new Y(2, (Object[])null);\n" +
644
			"	              ^^^^^^^^^^^^^^\n" +
645
			"Type mismatch: required \'@NonNull Object[]\' but the provided value is null\n" +
646
			"----------\n",
647
		this.LIBS,
648
		true /* shouldFlush*/);
649
}
650
// Bug 365983 - [compiler][null] AIOOB with null annotation analysis and varargs
651
public void test_nonnull_parameter_017() {
652
	if (this.complianceLevel > ClassFileConstants.JDK1_7) {
653
		fail("Reminder: should check if JSR 308 mandates a change in handling vararg elements (see bug 365983).");
654
	}
655
}
553
// assigning potential null to a nonnull local variable
656
// assigning potential null to a nonnull local variable
554
public void test_nonnull_local_001() {
657
public void test_nonnull_local_001() {
555
	runNegativeTest(
658
	runNegativeTest(
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java (-3 / +23 lines)
Lines 8-16 Link Here
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contributions for
10
 *     Stephan Herrmann - Contributions for
11
 *     							bug 335093 - [compiler][null] minimal hook for future null annotation support
11
 *								bug 335093 - [compiler][null] minimal hook for future null annotation support
12
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
12
 *								bug 349326 - [1.7] new warning for missing try-with-resources
13
 *								bug 186342 - [compiler][null] Using annotations for null checking
13
 *								bug 186342 - [compiler][null] Using annotations for null checking
14
 *								bug 365983 - [compiler][null] AIOOB with null annotation analysis and varargs
14
 *******************************************************************************/
15
 *******************************************************************************/
15
package org.eclipse.jdt.internal.compiler.ast;
16
package org.eclipse.jdt.internal.compiler.ast;
16
17
Lines 64-70 Link Here
64
{
65
{
65
	// compare actual null-status against parameter annotations of the called method:
66
	// compare actual null-status against parameter annotations of the called method:
66
	if (arguments != null && methodBinding.parameterNonNullness != null) {
67
	if (arguments != null && methodBinding.parameterNonNullness != null) {
67
		for (int i = 0; i < arguments.length; i++) {
68
69
		// check if varargs need special treatment:
70
		int numParamsToCheck = methodBinding.parameters.length;
71
		boolean passThrough = false;
72
		if (methodBinding.isVarargs()) {
73
			int varArgPos = numParamsToCheck-1;
74
			// this if-block essentially copied from generateArguments(..):
75
			if (numParamsToCheck == arguments.length) {
76
				TypeBinding varArgsType = methodBinding.parameters[varArgPos];
77
				TypeBinding lastType = arguments[varArgPos].resolvedType;
78
				if (lastType == TypeBinding.NULL
79
						|| (varArgsType.dimensions() == lastType.dimensions()
80
						&& lastType.isCompatibleWith(varArgsType)))
81
					passThrough = true; // pass directly as-is
82
			}
83
			if (!passThrough)
84
				numParamsToCheck--; // with non-passthrough varargs last param is fed from individual args -> don't check
85
		}
86
87
		for (int i = 0; i < numParamsToCheck; i++) {
68
			if (methodBinding.parameterNonNullness[i] == Boolean.TRUE) {
88
			if (methodBinding.parameterNonNullness[i] == Boolean.TRUE) {
69
				TypeBinding expectedType = methodBinding.parameters[i];
89
				TypeBinding expectedType = methodBinding.parameters[i];
70
				Expression argument = arguments[i];
90
				Expression argument = arguments[i];

Return to bug 365983