View | Details | Raw Unified | Return to bug 358903 | Differences between
and this patch

Collapse All | Expand All

(-)a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryWithResourcesStatementTest.java (-7 / +775 lines)
Lines 11-21 Link Here
11
 *     							bug 358827 - [1.7] exception analysis for t-w-r spoils null analysis
11
 *     							bug 358827 - [1.7] exception analysis for t-w-r spoils null analysis
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 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
13
 *     							bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
14
 *								bug 358903 - Filter practically unimportant resource leak warnings
15
 *								bug 360908 - Avoid resource leak warning when the underlying/chained resource is closed explicitly
16
 *								bug 361073 - Avoid resource leak warning when the top level resource is closed explicitly
17
 *								bug 362331 - Resource leak not detected when closeable not assigned to variable
18
 *								bug 362332 - Only report potential leak when closeable not created in the local scope
14
 *******************************************************************************/
19
 *******************************************************************************/
15
package org.eclipse.jdt.core.tests.compiler.regression;
20
package org.eclipse.jdt.core.tests.compiler.regression;
16
21
22
import java.io.IOException;
23
import java.net.URL;
17
import java.util.Map;
24
import java.util.Map;
18
25
26
import org.eclipse.core.runtime.FileLocator;
27
import org.eclipse.core.runtime.Path;
28
import org.eclipse.core.runtime.Platform;
19
import org.eclipse.jdt.core.JavaCore;
29
import org.eclipse.jdt.core.JavaCore;
20
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
30
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
21
31
Lines 23-29 Link Here
23
public class TryWithResourcesStatementTest extends AbstractRegressionTest {
33
public class TryWithResourcesStatementTest extends AbstractRegressionTest {
24
34
25
static {
35
static {
26
//	TESTS_NAMES = new String[] { "test056throw"};
36
//	TESTS_NAMES = new String[] { "test061a"};
27
//	TESTS_NUMBERS = new int[] { 50 };
37
//	TESTS_NUMBERS = new int[] { 50 };
28
//	TESTS_RANGE = new int[] { 11, -1 };
38
//	TESTS_RANGE = new int[] { 11, -1 };
29
}
39
}
Lines 3713-3723 Link Here
3713
		options);
3723
		options);
3714
}
3724
}
3715
// Bug 349326 - [1.7] new warning for missing try-with-resources
3725
// Bug 349326 - [1.7] new warning for missing try-with-resources
3726
// Bug 362332 - Only report potential leak when closeable not created in the local scope
3716
// one method returns an AutoCleasble, a second method uses this object without ever closing it.
3727
// one method returns an AutoCleasble, a second method uses this object without ever closing it.
3717
public void test056e() {
3728
public void test056e() {
3718
	Map options = getCompilerOptions();
3729
	Map options = getCompilerOptions();
3719
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3730
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
3720
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
3731
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
3721
	this.runNegativeTest(
3732
	this.runNegativeTest(
3722
		new String[] {
3733
		new String[] {
3723
			"X.java",
3734
			"X.java",
Lines 3744-3750 Link Here
3744
		"1. ERROR in X.java (at line 11)\n" + 
3755
		"1. ERROR in X.java (at line 11)\n" + 
3745
		"	FileReader reader = getReader(\"somefile\");\n" + 
3756
		"	FileReader reader = getReader(\"somefile\");\n" + 
3746
		"	           ^^^^^^\n" + 
3757
		"	           ^^^^^^\n" + 
3747
		"Resource leak: 'reader' is never closed\n" + 
3758
		"Potential resource leak: \'reader\' may not be closed\n" + 
3748
		"----------\n",
3759
		"----------\n",
3749
		null,
3760
		null,
3750
		true,
3761
		true,
Lines 3964-3969 Link Here
3964
		null,
3975
		null,
3965
		true,
3976
		true,
3966
		options);
3977
		options);
3978
}
3979
// Bug 349326 - [1.7] new warning for missing try-with-resources
3980
// three AutoCloseables in different blocks of the same method - problems ignored
3981
public void test056i_ignore() {
3982
	Map options = getCompilerOptions();
3983
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.IGNORE);
3984
	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.IGNORE);
3985
	options.put(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE, CompilerOptions.IGNORE);
3986
	this.runConformTest(
3987
		new String[] {
3988
			"X.java",
3989
			"import java.io.File;\n" +
3990
			"import java.io.FileReader;\n" +
3991
			"import java.io.IOException;\n" +
3992
			"public class X {\n" +
3993
			"    void foo(boolean f1, boolean f2) throws IOException {\n" +
3994
			"        File file = new File(\"somefile\");\n" +
3995
			"        if (f1) {\n" +
3996
			"            FileReader fileReader = new FileReader(file); // err: not closed\n" +
3997
			"            char[] in = new char[50];\n" +
3998
			"            fileReader.read(in);\n" +
3999
			"            while (true) {\n" +
4000
			"                 FileReader loopReader = new FileReader(file); // don't warn, properly closed\n" +
4001
			"                 loopReader.close();" +
4002
			"                 break;\n" +
4003
			"            }\n" +
4004
			"        } else {\n" +
4005
			"            FileReader fileReader = new FileReader(file); // warn: not closed on all paths\n" +
4006
			"            if (f2)\n" +
4007
			"                fileReader.close();\n" +
4008
			"        }\n" +
4009
			"    }\n" +
4010
			"}\n"
4011
		},
4012
		"",
4013
		null,
4014
		true,
4015
		null,
4016
		options,
4017
		null);
3967
}
4018
}
3968
// Bug 349326 - [1.7] new warning for missing try-with-resources
4019
// Bug 349326 - [1.7] new warning for missing try-with-resources
3969
// three AutoCloseables in different blocks of the same method
4020
// three AutoCloseables in different blocks of the same method
Lines 4358-4368 Link Here
4358
		null/*requestor*/);
4409
		null/*requestor*/);
4359
}
4410
}
4360
// Bug 349326 - [1.7] new warning for missing try-with-resources
4411
// Bug 349326 - [1.7] new warning for missing try-with-resources
4412
// Bug 362332 - Only report potential leak when closeable not created in the local scope
4361
// a method uses an AutoCloseable without ever closing it, type from a type variable
4413
// a method uses an AutoCloseable without ever closing it, type from a type variable
4362
public void test056p() {
4414
public void test056p() {
4363
	Map options = getCompilerOptions();
4415
	Map options = getCompilerOptions();
4364
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
4416
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
4365
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
4417
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
4366
	this.runNegativeTest(
4418
	this.runNegativeTest(
4367
		new String[] {
4419
		new String[] {
4368
			"X.java",
4420
			"X.java",
Lines 4389-4395 Link Here
4389
		"1. ERROR in X.java (at line 8)\n" + 
4441
		"1. ERROR in X.java (at line 8)\n" + 
4390
		"	T fileReader = newReader(file);\n" + 
4442
		"	T fileReader = newReader(file);\n" + 
4391
		"	  ^^^^^^^^^^\n" + 
4443
		"	  ^^^^^^^^^^\n" + 
4392
		"Resource leak: 'fileReader' is never closed\n" +
4444
		"Potential resource leak: \'fileReader\' may not be closed\n" +
4393
		"----------\n",
4445
		"----------\n",
4394
		null,
4446
		null,
4395
		true,
4447
		true,
Lines 4444-4450 Link Here
4444
		options);
4496
		options);
4445
}
4497
}
4446
// Bug 349326 - [1.7] new warning for missing try-with-resources
4498
// Bug 349326 - [1.7] new warning for missing try-with-resources
4447
// closed in dead code
4499
// properly closed, dead code in between
4448
public void test056r() {
4500
public void test056r() {
4449
	Map options = getCompilerOptions();
4501
	Map options = getCompilerOptions();
4450
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
4502
	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
Lines 5354-5360 Link Here
5354
		"X::~X\n" + 
5406
		"X::~X\n" + 
5355
		"true");
5407
		"true");
5356
}
5408
}
5357
5409
// Bug 358903 - Filter practically unimportant resource leak warnings
5410
// Bug 360908 - Avoid resource leak warning when the underlying/chained resource is closed explicitly
5411
// a resource wrapper is not closed but the underlying resource is
5412
public void test061a() {
5413
	Map options = getCompilerOptions();
5414
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
5415
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
5416
	this.runConformTest(
5417
		new String[] {
5418
			"X.java",
5419
			"import java.io.File;\n" +
5420
			"import java.io.BufferedInputStream;\n" +
5421
			"import java.io.FileInputStream;\n" +
5422
			"import java.io.IOException;\n" +
5423
			"public class X {\n" +
5424
			"    void foo() throws IOException {\n" +
5425
			"        File file = new File(\"somefile\");\n" +
5426
			"        FileInputStream fileStream  = new FileInputStream(file);\n" +
5427
			"        BufferedInputStream bis = new BufferedInputStream(fileStream);\n" +
5428
			"        BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
5429
			"        System.out.println(bis.available());\n" +
5430
			"        fileStream.close();\n" +
5431
			"    }\n" +
5432
			"    void inline() throws IOException {\n" +
5433
			"        File file = new File(\"somefile\");\n" +
5434
			"        FileInputStream fileStream;\n" +
5435
			"        BufferedInputStream bis = new BufferedInputStream(fileStream = new FileInputStream(file));\n" +
5436
			"        System.out.println(bis.available());\n" +
5437
			"        fileStream.close();\n" +
5438
			"    }\n" +
5439
			"    public static void main(String[] args) throws IOException {\n" +
5440
			"        try {\n" +
5441
			"            new X().foo();\n" +
5442
			"        } catch (IOException ex) {" +
5443
			"            System.out.println(\"Got IO Exception\");\n" +
5444
			"        }\n" +
5445
			"    }\n" +
5446
			"}\n"
5447
		},
5448
		"Got IO Exception",
5449
		null,
5450
		true,
5451
		null,
5452
		options,
5453
		null);
5454
}
5455
// Bug 358903 - Filter practically unimportant resource leak warnings
5456
// a closeable without OS resource is not closed
5457
public void test061b() {
5458
	Map options = getCompilerOptions();
5459
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
5460
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
5461
	this.runConformTest(
5462
		new String[] {
5463
			"X.java",
5464
			"import java.io.StringReader;\n" +
5465
			"import java.io.IOException;\n" +
5466
			"public class X {\n" +
5467
			"    void foo() throws IOException {\n" +
5468
			"        StringReader string  = new StringReader(\"content\");\n" +
5469
			"        System.out.println(string.read());\n" +
5470
			"    }\n" +
5471
			"    public static void main(String[] args) throws IOException {\n" +
5472
			"        new X().foo();\n" +
5473
			"    }\n" +
5474
			"}\n"
5475
		},
5476
		"99", // character 'c'
5477
		null,
5478
		true,
5479
		null,
5480
		options,
5481
		null);
5482
}
5483
// Bug 358903 - Filter practically unimportant resource leak warnings
5484
// a resource wrapper is not closed but the underlying closeable is resource-free
5485
public void test061c() {
5486
	Map options = getCompilerOptions();
5487
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
5488
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
5489
	this.runConformTest(
5490
		new String[] {
5491
			"X.java",
5492
			"import java.io.BufferedReader;\n" +
5493
			"import java.io.StringReader;\n" +
5494
			"import java.io.IOException;\n" +
5495
			"public class X {\n" +
5496
			"    void foo() throws IOException {\n" +
5497
			"        StringReader input = new StringReader(\"content\");\n" +
5498
			"        BufferedReader br = new BufferedReader(input);\n" +
5499
			"        BufferedReader doubleWrap = new BufferedReader(br);\n" +
5500
			"        System.out.println(br.read());\n" +
5501
			"    }\n" +
5502
			"    void inline() throws IOException {\n" +
5503
			"        BufferedReader br = new BufferedReader(new StringReader(\"content\"));\n" +
5504
			"        System.out.println(br.read());\n" +
5505
			"    }\n" +
5506
			"    public static void main(String[] args) throws IOException {\n" +
5507
			"        new X().foo();\n" +
5508
			"    }\n" +
5509
			"}\n"
5510
		},
5511
		"99",
5512
		null,
5513
		true,
5514
		null,
5515
		options,
5516
		null);
5517
}
5518
// Bug 358903 - Filter practically unimportant resource leak warnings
5519
// a resource wrapper is not closed neither is the underlying resource
5520
public void test061d() {
5521
	Map options = getCompilerOptions();
5522
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
5523
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.WARNING);
5524
	this.runNegativeTest(
5525
		new String[] {
5526
			"X.java",
5527
			"import java.io.File;\n" +
5528
			"import java.io.BufferedInputStream;\n" +
5529
			"import java.io.FileInputStream;\n" +
5530
			"import java.io.IOException;\n" +
5531
			"public class X {\n" +
5532
			"    void foo() throws IOException {\n" +
5533
			"        File file = new File(\"somefile\");\n" +
5534
			"        FileInputStream fileStream  = new FileInputStream(file);\n" +
5535
			"        BufferedInputStream bis = new BufferedInputStream(fileStream);\n" +
5536
			"        BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
5537
			"        System.out.println(bis.available());\n" +
5538
			"    }\n" +
5539
			"    void inline() throws IOException {\n" +
5540
			"        File file = new File(\"somefile\");\n" +
5541
			"        BufferedInputStream bis2 = new BufferedInputStream(new FileInputStream(file));\n" +
5542
			"        System.out.println(bis2.available());\n" +
5543
			"    }\n" +
5544
			"    public static void main(String[] args) throws IOException {\n" +
5545
			"        try {\n" +
5546
			"            new X().foo();\n" +
5547
			"        } catch (IOException ex) {" +
5548
			"            System.out.println(\"Got IO Exception\");\n" +
5549
			"        }\n" +
5550
			"    }\n" +
5551
			"}\n"
5552
		},
5553
		"----------\n" + 
5554
		"1. ERROR in X.java (at line 10)\n" + 
5555
		"	BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" + 
5556
		"	                    ^^^^^^^^^^\n" + 
5557
		"Resource leak: \'doubleWrap\' is never closed\n" + 
5558
		"----------\n" + 
5559
		"2. ERROR in X.java (at line 15)\n" + 
5560
		"	BufferedInputStream bis2 = new BufferedInputStream(new FileInputStream(file));\n" + 
5561
		"	                    ^^^^\n" + 
5562
		"Resource leak: \'bis2\' is never closed\n" + 
5563
		"----------\n",
5564
		null,
5565
		true,
5566
		options);
5567
}
5568
// Bug 358903 - Filter practically unimportant resource leak warnings
5569
// Bug 361073 - Avoid resource leak warning when the top level resource is closed explicitly
5570
// a resource wrapper is closed closing also the underlying resource
5571
public void test061e() {
5572
	Map options = getCompilerOptions();
5573
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
5574
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
5575
	this.runConformTest(
5576
		new String[] {
5577
			"X.java",
5578
			"import java.io.File;\n" +
5579
			"import java.io.BufferedInputStream;\n" +
5580
			"import java.io.FileInputStream;\n" +
5581
			"import java.io.IOException;\n" +
5582
			"public class X {\n" +
5583
			"    FileInputStream fis;" +
5584
			"    void foo() throws IOException {\n" +
5585
			"        File file = new File(\"somefile\");\n" +
5586
			"        FileInputStream fileStream  = new FileInputStream(file);\n" +
5587
			"        BufferedInputStream bis = new BufferedInputStream(fileStream);\n" +
5588
			"        BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
5589
			"        System.out.println(bis.available());\n" +
5590
			"        bis.close();\n" +
5591
			"    }\n" +
5592
			"    void inline() throws IOException {\n" +
5593
			"        File file = new File(\"somefile\");\n" +
5594
			"        BufferedInputStream bis2 = new BufferedInputStream(fis = new FileInputStream(file));\n" + // field assignment
5595
			"        System.out.println(bis2.available());\n" +
5596
			"        bis2.close();\n" +
5597
			"        FileInputStream fileStream  = null;\n" +
5598
			"        BufferedInputStream bis3 = new BufferedInputStream(fileStream = new FileInputStream(file));\n" +
5599
			"        System.out.println(bis3.available());\n" +
5600
			"        bis3.close();\n" +
5601
			"    }\n" +
5602
			"    public static void main(String[] args) throws IOException {\n" +
5603
			"        try {\n" +
5604
			"            new X().foo();\n" +
5605
			"        } catch (IOException ex) {" +
5606
			"            System.out.println(\"Got IO Exception\");\n" +
5607
			"        }\n" +
5608
			"    }\n" +
5609
			"}\n"
5610
		},
5611
		"Got IO Exception",
5612
		null,
5613
		true,
5614
		null,
5615
		options,
5616
		null);
5617
}
5618
// Bug 358903 - Filter practically unimportant resource leak warnings
5619
// Bug 361073 - Avoid resource leak warning when the top level resource is closed explicitly
5620
// a resource wrapper is closed closing also the underlying resource - original test case
5621
public void test061f() throws IOException {
5622
	Map options = getCompilerOptions();
5623
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
5624
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
5625
	URL url = FileLocator.toFileURL(FileLocator.find(Platform.getBundle("org.eclipse.jdt.core.tests.compiler"), new Path("META-INF/MANIFEST.MF"), null));
5626
	this.runConformTest(
5627
		new String[] {
5628
			"X.java",
5629
			"import java.io.InputStream;\n" +
5630
			"import java.io.InputStreamReader;\n" +
5631
			"import java.io.BufferedReader;\n" +
5632
			"import java.io.IOException;\n" +
5633
			"import java.net.URL;\n" +
5634
			"public class X {\n" +
5635
			"    boolean loadURL(final URL url) throws IOException {\n" + 
5636
			"        InputStream stream = null;\n" + 
5637
			"        BufferedReader reader = null;\n" + 
5638
			"        try {\n" + 
5639
			"            stream = url.openStream();\n" + 
5640
			"            reader = new BufferedReader(new InputStreamReader(stream));\n" + 
5641
			"            System.out.println(reader.readLine());\n" +
5642
			"        } finally {\n" + 
5643
			"            try {\n" + 
5644
			"                if (reader != null)\n" + 
5645
			"                    reader.close();\n" + 
5646
			"            } catch (IOException x) {\n" + 
5647
			"            }\n" + 
5648
			"        }\n" + 
5649
			"        return false; // 'stream' may not be closed at this location\n" + 
5650
			"    }\n" + 
5651
			"    public static void main(String[] args) throws IOException {\n" +
5652
			"        try {\n" +
5653
			"            new X().loadURL(new URL(\""+url.toString()+"\"));\n" +
5654
			"        } catch (IOException ex) {\n" +
5655
			"            System.out.println(\"Got IO Exception\"+ex);\n" +
5656
			"        }\n" +
5657
			"    }\n" +
5658
			"}\n"
5659
		},
5660
		"Manifest-Version: 1.0",
5661
		null,
5662
		true,
5663
		null,
5664
		options,
5665
		null);
5666
}
5667
// Bug 358903 - Filter practically unimportant resource leak warnings
5668
// Bug 360908 - Avoid resource leak warning when the underlying/chained resource is closed explicitly
5669
// Different points in a resource chain are closed
5670
public void test061g() {
5671
	Map options = getCompilerOptions();
5672
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
5673
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
5674
	this.runNegativeTest(
5675
		new String[] {
5676
			"X.java",
5677
			"import java.io.File;\n" +
5678
			"import java.io.BufferedInputStream;\n" +
5679
			"import java.io.FileInputStream;\n" +
5680
			"import java.io.IOException;\n" +
5681
			"public class X {\n" +
5682
			"    void closeMiddle() throws IOException {\n" +
5683
			"        File file = new File(\"somefile\");\n" +
5684
			"        FileInputStream fileStream  = new FileInputStream(file);\n" +
5685
			"        BufferedInputStream bis = new BufferedInputStream(fileStream);\n" +
5686
			"        BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
5687
			"        System.out.println(bis.available());\n" +
5688
			"        bis.close();\n" +
5689
			"    }\n" +
5690
			"    void closeOuter() throws IOException {\n" +
5691
			"        File file2 = new File(\"somefile\");\n" +
5692
			"        FileInputStream fileStream2  = new FileInputStream(file2);\n" +
5693
			"        BufferedInputStream bis2 = new BufferedInputStream(fileStream2);\n" +
5694
			"        BufferedInputStream doubleWrap2 = new BufferedInputStream(bis2);\n" +
5695
			"        System.out.println(bis2.available());\n" +
5696
			"        doubleWrap2.close();\n" +
5697
			"    }\n" +
5698
			"    void neverClosed() throws IOException {\n" +
5699
			"        File file3 = new File(\"somefile\");\n" +
5700
			"        FileInputStream fileStream3  = new FileInputStream(file3);\n" +
5701
			"        BufferedInputStream bis3 = new BufferedInputStream(fileStream3);\n" +
5702
			"        BufferedInputStream doubleWrap3 = new BufferedInputStream(bis3);\n" +
5703
			"        System.out.println(doubleWrap3.available());\n" +
5704
			"    }\n" +
5705
			"}\n"
5706
		},
5707
		"----------\n" + 
5708
		"1. ERROR in X.java (at line 26)\n" + 
5709
		"	BufferedInputStream doubleWrap3 = new BufferedInputStream(bis3);\n" + 
5710
		"	                    ^^^^^^^^^^^\n" + 
5711
		"Resource leak: \'doubleWrap3\' is never closed\n" + 
5712
		"----------\n",
5713
		null,
5714
		true,
5715
		options);
5716
}
5717
// Bug 358903 - Filter practically unimportant resource leak warnings
5718
// Bug 360908 - Avoid resource leak warning when the underlying/chained resource is closed explicitly
5719
// Different points in a resource chain are potentially closed
5720
public void test061h() {
5721
	Map options = getCompilerOptions();
5722
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
5723
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
5724
	this.runNegativeTest(
5725
		new String[] {
5726
			"X.java",
5727
			"import java.io.File;\n" +
5728
			"import java.io.BufferedInputStream;\n" +
5729
			"import java.io.FileInputStream;\n" +
5730
			"import java.io.IOException;\n" +
5731
			"public class X {\n" +
5732
			"    void closeMiddle(boolean b) throws IOException {\n" +
5733
			"        File file = new File(\"somefile\");\n" +
5734
			"        FileInputStream fileStream  = new FileInputStream(file);\n" +
5735
			"        BufferedInputStream bis = new BufferedInputStream(fileStream);\n" +
5736
			"        BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" +
5737
			"        System.out.println(bis.available());\n" +
5738
			"        if (b)\n" +
5739
			"            bis.close();\n" +
5740
			"    }\n" +
5741
			"    void closeOuter(boolean b) throws IOException {\n" +
5742
			"        File file2 = new File(\"somefile\");\n" +
5743
			"        FileInputStream fileStream2  = new FileInputStream(file2);\n" +
5744
			"        BufferedInputStream dummy;\n" +
5745
			"        BufferedInputStream bis2 = (dummy = new BufferedInputStream(fileStream2));\n" +
5746
			"        BufferedInputStream doubleWrap2 = new BufferedInputStream(bis2);\n" +
5747
			"        System.out.println(bis2.available());\n" +
5748
			"        if (b)\n" +
5749
			"            doubleWrap2.close();\n" +
5750
			"    }\n" +
5751
			"    void potAndDef(boolean b) throws IOException {\n" +
5752
			"        File file3 = new File(\"somefile\");\n" +
5753
			"        FileInputStream fileStream3  = new FileInputStream(file3);\n" +
5754
			"        BufferedInputStream bis3 = new BufferedInputStream(fileStream3);\n" +
5755
			"        BufferedInputStream doubleWrap3 = new BufferedInputStream(bis3);\n" +
5756
			"        System.out.println(doubleWrap3.available());\n" +
5757
			"        if (b) bis3.close();\n" +
5758
			"        fileStream3.close();\n" +
5759
			"    }\n" +
5760
			"}\n"
5761
		},
5762
		"----------\n" + 
5763
		"1. ERROR in X.java (at line 10)\n" + 
5764
		"	BufferedInputStream doubleWrap = new BufferedInputStream(bis);\n" + 
5765
		"	                    ^^^^^^^^^^\n" + 
5766
		"Potential resource leak: \'doubleWrap\' may not be closed\n" + 
5767
		"----------\n" + 
5768
		"2. ERROR in X.java (at line 20)\n" + 
5769
		"	BufferedInputStream doubleWrap2 = new BufferedInputStream(bis2);\n" + 
5770
		"	                    ^^^^^^^^^^^\n" + 
5771
		"Potential resource leak: \'doubleWrap2\' may not be closed\n" + 
5772
		"----------\n",
5773
		null,
5774
		true,
5775
		options);
5776
}
5777
// Bug 358903 - Filter practically unimportant resource leak warnings
5778
// local var is re-used for two levels of wrappers
5779
public void test061i() {
5780
	Map options = getCompilerOptions();
5781
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
5782
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
5783
	this.runNegativeTest(
5784
		new String[] {
5785
			"X.java",
5786
			"import java.io.File;\n" +
5787
			"import java.io.InputStream;\n" +
5788
			"import java.io.BufferedInputStream;\n" +
5789
			"import java.io.FileInputStream;\n" +
5790
			"import java.io.IOException;\n" +
5791
			"public class X {\n" +
5792
			"    void closeMiddle() throws IOException {\n" +
5793
			"        File file = new File(\"somefile\");\n" +
5794
			"        InputStream stream  = new FileInputStream(file);\n" +
5795
			"        stream = new BufferedInputStream(stream);\n" +
5796
			"        InputStream middle;\n" +
5797
			"        stream = new BufferedInputStream(middle = stream);\n" +
5798
			"        System.out.println(stream.available());\n" +
5799
			"        middle.close();\n" +
5800
			"    }\n" +
5801
			"    void closeOuter() throws IOException {\n" +
5802
			"        File file = new File(\"somefile\");\n" +
5803
			"        InputStream stream2  = new FileInputStream(file);\n" +
5804
			"        stream2 = new BufferedInputStream(stream2);\n" +
5805
			"        stream2 = new BufferedInputStream(stream2);\n" +
5806
			"        System.out.println(stream2.available());\n" +
5807
			"        stream2.close();\n" +
5808
			"    }\n" +
5809
			"    void neverClosed() throws IOException {\n" +
5810
			"        File file = new File(\"somefile\");\n" +
5811
			"        InputStream stream3  = new FileInputStream(file);\n" +
5812
			"        stream3 = new BufferedInputStream(stream3);\n" +
5813
			"        stream3 = new BufferedInputStream(stream3);\n" +
5814
			"        System.out.println(stream3.available());\n" +
5815
			"    }\n" +
5816
			"}\n"
5817
		},
5818
		"----------\n" + 
5819
		"1. ERROR in X.java (at line 26)\n" + 
5820
		"	InputStream stream3  = new FileInputStream(file);\n" + 
5821
		"	            ^^^^^^^\n" + 
5822
		"Resource leak: \'stream3\' is never closed\n" + 
5823
		"----------\n",
5824
		null,
5825
		true,
5826
		options);
5827
}
5828
// Bug 358903 - Filter practically unimportant resource leak warnings
5829
// self-wrapping a method argument (caused NPE UnconditionalFlowInfo.markAsDefinitelyNull(..)).
5830
public void test061j() {
5831
	Map options = getCompilerOptions();
5832
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
5833
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
5834
	this.runConformTest(
5835
		new String[] {
5836
			"X.java",
5837
			"import java.io.InputStream;\n" +
5838
			"import java.io.BufferedInputStream;\n" +
5839
			"import java.io.IOException;\n" +
5840
			"public class X {\n" +
5841
			"    void foo(InputStream stream) throws IOException {\n" +
5842
			"        stream = new BufferedInputStream(stream);\n" +
5843
			"        System.out.println(stream.available());\n" +
5844
			"        stream.close();\n" +
5845
			"    }\n" +
5846
			"    void boo(InputStream stream2) throws IOException {\n" +
5847
			"        stream2 = new BufferedInputStream(stream2);\n" +
5848
			"        System.out.println(stream2.available());\n" +
5849
			"    }\n" +
5850
			"}\n"
5851
		},
5852
		"",
5853
		null,
5854
		true,
5855
		null,
5856
		options,
5857
		null);
5858
}
5859
// Bug 358903 - Filter practically unimportant resource leak warnings
5860
// a wrapper is created in a return statement
5861
public void test061k() throws IOException {
5862
	Map options = getCompilerOptions();
5863
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
5864
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
5865
	this.runConformTest(
5866
		new String[] {
5867
			"X.java",
5868
			"import java.io.File;\n" +
5869
			"import java.io.FileInputStream;\n" +
5870
			"import java.io.BufferedInputStream;\n" +
5871
			"import java.io.IOException;\n" +
5872
			"public class X {\n" +
5873
			"    BufferedInputStream getReader(File file) throws IOException {\n" +
5874
			"        FileInputStream stream = new FileInputStream(file);\n" +
5875
			"        return new BufferedInputStream(stream);\n" +
5876
			"    }\n" +
5877
			"}\n"
5878
		},
5879
		"",
5880
		null,
5881
		true,
5882
		null,
5883
		options,
5884
		null);
5885
}
5886
// Bug 358903 - Filter practically unimportant resource leak warnings
5887
// a closeable is assigned to a field
5888
public void test061l() throws IOException {
5889
	Map options = getCompilerOptions();
5890
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
5891
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
5892
	this.runConformTest(
5893
		new String[] {
5894
			"X.java",
5895
			"import java.io.File;\n" +
5896
			"import java.io.FileInputStream;\n" +
5897
			"import java.io.BufferedInputStream;\n" +
5898
			"import java.io.IOException;\n" +
5899
			"public class X {\n" +
5900
			"    BufferedInputStream stream;\n" +
5901
			"    void foo(File file) throws IOException {\n" +
5902
			"        FileInputStream s = new FileInputStream(file);\n" +
5903
			"        stream = new BufferedInputStream(s);\n" +
5904
			"    }\n" +
5905
			"}\n"
5906
		},
5907
		"",
5908
		null,
5909
		true,
5910
		null,
5911
		options,
5912
		null);
5913
}
5914
// Bug 362331 - Resource leak not detected when closeable not assigned to variable
5915
// a resource is never assigned
5916
public void test062a() throws IOException {
5917
	Map options = getCompilerOptions();
5918
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
5919
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
5920
	this.runNegativeTest(
5921
		new String[] {
5922
			"X.java",
5923
			"import java.io.File;\n" +
5924
			"import java.io.FileOutputStream;\n" +
5925
			"import java.io.IOException;\n" +
5926
			"public class X {\n" +
5927
			"    void foo() throws IOException {\n" +
5928
			"        new FileOutputStream(new File(\"C:\\temp\\foo.txt\")).write(1);\n" + 
5929
			"    }\n" +
5930
			"}\n"
5931
		},
5932
		"----------\n" + 
5933
		"1. ERROR in X.java (at line 6)\n" + 
5934
		"	new FileOutputStream(new File(\"C:\\temp\\foo.txt\")).write(1);\n" + 
5935
		"	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
5936
		"Resource leak: \'<unassigned Closeable value>\' is never closed\n" + 
5937
		"----------\n",
5938
		null,
5939
		true,
5940
		options);
5941
}
5942
// Bug 362331 - Resource leak not detected when closeable not assigned to variable
5943
// a freshly allocated resource is immediately closed
5944
public void test062b() throws IOException {
5945
	Map options = getCompilerOptions();
5946
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
5947
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
5948
	this.runConformTest(
5949
		new String[] {
5950
			"X.java",
5951
			"import java.io.File;\n" +
5952
			"import java.io.FileOutputStream;\n" +
5953
			"import java.io.IOException;\n" +
5954
			"public class X {\n" +
5955
			"    void foo() throws IOException {\n" +
5956
			"        new FileOutputStream(new File(\"C:\\temp\\foo.txt\")).close();\n" + 
5957
			"    }\n" +
5958
			"}\n"
5959
		},
5960
		"",
5961
		null,
5962
		true,
5963
		null,
5964
		options,
5965
		null);
5966
}
5967
// Bug 362331 - Resource leak not detected when closeable not assigned to variable
5968
// a resource is directly passed to another method
5969
public void test062c() throws IOException {
5970
	Map options = getCompilerOptions();
5971
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
5972
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
5973
	this.runConformTest(
5974
		new String[] {
5975
			"X.java",
5976
			"import java.io.File;\n" +
5977
			"import java.io.FileOutputStream;\n" +
5978
			"import java.io.IOException;\n" +
5979
			"public class X {\n" +
5980
			"    void foo() throws IOException {\n" +
5981
			"        writeIt(new FileOutputStream(new File(\"C:\\temp\\foo.txt\")));\n" + 
5982
			"    }\n" +
5983
			"    void writeIt(FileOutputStream fos) throws IOException {\n" +
5984
			"        fos.write(1);\n" +
5985
			"        fos.close();\n" +
5986
			"    }\n" +
5987
			"}\n"
5988
		},
5989
		"",
5990
		null,
5991
		true,
5992
		null,
5993
		options,
5994
		null);
5995
}
5996
// Bug 362331 - Resource leak not detected when closeable not assigned to variable
5997
// a resource is not used
5998
public void test062d() throws IOException {
5999
	Map options = getCompilerOptions();
6000
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
6001
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
6002
	this.runNegativeTest(
6003
		new String[] {
6004
			"X.java",
6005
			"import java.io.File;\n" +
6006
			"import java.io.FileOutputStream;\n" +
6007
			"import java.io.IOException;\n" +
6008
			"public class X {\n" +
6009
			"    void foo() throws IOException {\n" +
6010
			"        new FileOutputStream(new File(\"C:\\temp\\foo.txt\"));\n" + 
6011
			"    }\n" +
6012
			"}\n"
6013
		},
6014
		"----------\n" + 
6015
		"1. ERROR in X.java (at line 6)\n" + 
6016
		"	new FileOutputStream(new File(\"C:\\temp\\foo.txt\"));\n" + 
6017
		"	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
6018
		"Resource leak: \'<unassigned Closeable value>\' is never closed\n" + 
6019
		"----------\n",
6020
		null,
6021
		true,
6022
		options);
6023
}
6024
// Bug 362332 - Only report potential leak when closeable not created in the local scope
6025
// a wrapper is obtained from another method
6026
public void test063a() throws IOException {
6027
	Map options = getCompilerOptions();
6028
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
6029
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
6030
	this.runNegativeTest(
6031
		new String[] {
6032
			"X.java",
6033
			"import java.io.File;\n" +
6034
			"import java.io.FileInputStream;\n" +
6035
			"import java.io.BufferedInputStream;\n" +
6036
			"import java.io.IOException;\n" +
6037
			"public class X {\n" +
6038
			"    void read(File file) throws IOException {\n" +
6039
			"        FileInputStream stream = new FileInputStream(file);\n" +
6040
			"        BufferedInputStream bis = new BufferedInputStream(stream); // never since reassigned\n" +
6041
			"        FileInputStream stream2 = new FileInputStream(file); // unsure since passed to method\n" +
6042
			"        bis = getReader(stream2); // unsure since obtained from method\n" +
6043
			"        bis.available();\n" +
6044
			"    }\n" +
6045
			"    BufferedInputStream getReader(FileInputStream stream) throws IOException {\n" +
6046
			"        return new BufferedInputStream(stream);\n" +
6047
			"    }\n" +
6048
			"}\n"
6049
		},
6050
		"----------\n" + 
6051
		"1. ERROR in X.java (at line 8)\n" + 
6052
		"	BufferedInputStream bis = new BufferedInputStream(stream); // never since reassigned\n" + 
6053
		"	                    ^^^\n" + 
6054
		"Resource leak: \'bis\' is never closed\n" + 
6055
		"----------\n" + 
6056
		"2. ERROR in X.java (at line 9)\n" + 
6057
		"	FileInputStream stream2 = new FileInputStream(file); // unsure since passed to method\n" + 
6058
		"	                ^^^^^^^\n" + 
6059
		"Potential resource leak: \'stream2\' may not be closed\n" + 
6060
		"----------\n" + 
6061
		"3. ERROR in X.java (at line 10)\n" + 
6062
		"	bis = getReader(stream2); // unsure since obtained from method\n" + 
6063
		"	^^^^^^^^^^^^^^^^^^^^^^^^\n" + 
6064
		"Potential resource leak: \'bis\' may not be closed\n" + 
6065
		"----------\n",
6066
		null,
6067
		true,
6068
		options);
6069
}
6070
// Bug 362332 - Only report potential leak when closeable not created in the local scope
6071
// a wrapper is obtained from a field read
6072
public void test063b() throws IOException {
6073
	Map options = getCompilerOptions();
6074
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
6075
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
6076
	this.runConformTest(
6077
		new String[] {
6078
			"X.java",
6079
			"import java.io.FileInputStream;\n" +
6080
			"import java.io.BufferedInputStream;\n" +
6081
			"import java.io.IOException;\n" +
6082
			"public class X {\n" +
6083
			"    FileInputStream stream;\n" +
6084
			"    void read() throws IOException {\n" +
6085
			"        FileInputStream s = this.stream;\n" +
6086
			"        BufferedInputStream bis = new BufferedInputStream(s); // don't complain since s is obtained from a field\n" +
6087
			"        bis.available();\n" +
6088
			"    }\n" +
6089
			"}\n"
6090
		},
6091
		"",
6092
		null,
6093
		true,
6094
		null,
6095
		options,
6096
		null);
6097
}
6098
// Bug 362332 - Only report potential leak when closeable not created in the local scope
6099
// a wrapper is assigned to a field
6100
public void test063c() throws IOException {
6101
	Map options = getCompilerOptions();
6102
	options.put(CompilerOptions.OPTION_ReportUnclosedCloseable, CompilerOptions.ERROR);
6103
	options.put(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, CompilerOptions.ERROR);
6104
	this.runConformTest(
6105
		new String[] {
6106
			"X.java",
6107
			"import java.io.FileInputStream;\n" +
6108
			"import java.io.BufferedInputStream;\n" +
6109
			"import java.io.IOException;\n" +
6110
			"public class X {\n" +
6111
			"    BufferedInputStream stream;\n" +
6112
			"    void read() throws IOException {\n" +
6113
			"        FileInputStream s = new FileInputStream(\"somefile\");\n" +
6114
			"        BufferedInputStream bis = new BufferedInputStream(s);\n" +
6115
			"        this.stream = bis;\n" +
6116
			"    }\n" +
6117
			"}\n"
6118
		},
6119
		"",
6120
		null,
6121
		true,
6122
		null,
6123
		options,
6124
		null);
6125
}
5358
public static Class testClass() {
6126
public static Class testClass() {
5359
	return TryWithResourcesStatementTest.class;
6127
	return TryWithResourcesStatementTest.class;
5360
}
6128
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java (-3 / +10 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 12-17 Link Here
12
 *     						bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
12
 *     						bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
13
 *     						bug 349326 - [1.7] new warning for missing try-with-resources
13
 *     						bug 349326 - [1.7] new warning for missing try-with-resources
14
 * 							bug 186342 - [compiler][null] Using annotations for null checking
14
 * 							bug 186342 - [compiler][null] Using annotations for null checking
15
 *							bug 358903 - Filter practically unimportant resource leak warnings
15
 *******************************************************************************/
16
 *******************************************************************************/
16
package org.eclipse.jdt.internal.compiler.ast;
17
package org.eclipse.jdt.internal.compiler.ast;
17
18
Lines 37-42 Link Here
37
	protected TypeBinding typeExpected;	  // for <> inference
38
	protected TypeBinding typeExpected;	  // for <> inference
38
	public boolean inferredReturnType;
39
	public boolean inferredReturnType;
39
40
41
	public FakedTrackingVariable closeTracker;	// when allocation a Closeable store a pre-liminary tracking variable here
42
40
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
43
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
41
	// check captured variables are initialized in current context (26134)
44
	// check captured variables are initialized in current context (26134)
42
	checkCapturedLocalInitializationIfNecessary((ReferenceBinding)this.binding.declaringClass.erasure(), currentScope, flowInfo);
45
	checkCapturedLocalInitializationIfNecessary((ReferenceBinding)this.binding.declaringClass.erasure(), currentScope, flowInfo);
Lines 44-61 Link Here
44
	// process arguments
47
	// process arguments
45
	if (this.arguments != null) {
48
	if (this.arguments != null) {
46
		for (int i = 0, count = this.arguments.length; i < count; i++) {
49
		for (int i = 0, count = this.arguments.length; i < count; i++) {
47
			// if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.)
48
			flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo);
49
			flowInfo =
50
			flowInfo =
50
				this.arguments[i]
51
				this.arguments[i]
51
					.analyseCode(currentScope, flowContext, flowInfo)
52
					.analyseCode(currentScope, flowContext, flowInfo)
52
					.unconditionalInits();
53
					.unconditionalInits();
54
			// if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.)
55
			flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo, this.resolvedType);
53
			if ((this.arguments[i].implicitConversion & TypeIds.UNBOXING) != 0) {
56
			if ((this.arguments[i].implicitConversion & TypeIds.UNBOXING) != 0) {
54
				this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
57
				this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
55
			}
58
			}
56
		}
59
		}
57
		analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments);
60
		analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments);
58
	}
61
	}
62
63
	if (FakedTrackingVariable.isAutoCloseable(this.resolvedType))
64
		FakedTrackingVariable.analyseCloseableAllocation(currentScope, flowInfo, this);
65
59
	// record some dependency information for exception types
66
	// record some dependency information for exception types
60
	ReferenceBinding[] thrownExceptions;
67
	ReferenceBinding[] thrownExceptions;
61
	if (((thrownExceptions = this.binding.thrownExceptions).length) != 0) {
68
	if (((thrownExceptions = this.binding.thrownExceptions).length) != 0) {
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java (-11 / +20 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 14-19 Link Here
14
 *     						bug 335093 - [compiler][null] minimal hook for future null annotation support
14
 *     						bug 335093 - [compiler][null] minimal hook for future null annotation support
15
 *     						bug 349326 - [1.7] new warning for missing try-with-resources
15
 *     						bug 349326 - [1.7] new warning for missing try-with-resources
16
 *							bug 186342 - [compiler][null] Using annotations for null checking
16
 *							bug 186342 - [compiler][null] Using annotations for null checking
17
 *							bug 358903 - Filter practically unimportant resource leak warnings
17
 *******************************************************************************/
18
 *******************************************************************************/
18
package org.eclipse.jdt.internal.compiler.ast;
19
package org.eclipse.jdt.internal.compiler.ast;
19
20
Lines 46-64 Link Here
46
	if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0) {
47
	if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0) {
47
		this.expression.checkNPE(currentScope, flowContext, flowInfo);
48
		this.expression.checkNPE(currentScope, flowContext, flowInfo);
48
	}
49
	}
50
	
51
	FlowInfo preInitInfo = null;
52
	boolean shouldAnalyseResource = local != null 
53
			&& flowInfo.reachMode() == FlowInfo.REACHABLE 
54
			&& (FakedTrackingVariable.isAutoCloseable(this.expression.resolvedType)
55
					|| this.expression.resolvedType == TypeBinding.NULL);
56
	if (shouldAnalyseResource) {
57
		preInitInfo = flowInfo.unconditionalCopy();
58
		// analysis of resource leaks needs additional context while analyzing the RHS:
59
		FakedTrackingVariable.preConnectTrackerAcrossAssignment(this, local, this.expression);
60
	}
61
	
49
	flowInfo = ((Reference) this.lhs)
62
	flowInfo = ((Reference) this.lhs)
50
		.analyseAssignment(currentScope, flowContext, flowInfo, this, false)
63
		.analyseAssignment(currentScope, flowContext, flowInfo, this, false)
51
		.unconditionalInits();
64
		.unconditionalInits();
52
	if (local != null) {
65
53
		LocalVariableBinding previousTrackerBinding = null;
66
	if (shouldAnalyseResource)
54
		if (local.closeTracker != null) {
67
		FakedTrackingVariable.handleResourceAssignment(preInitInfo, flowInfo, this, this.expression, local);
55
			// Assigning to a variable already holding an AutoCloseable, has it been closed before?
68
	else
56
			previousTrackerBinding = local.closeTracker.binding;
69
		FakedTrackingVariable.cleanUpAfterAssignment(currentScope, this.lhs.bits, this.expression);
57
			if (!flowInfo.isDefinitelyNull(local)) // only if previous value may be non-null
70
58
				local.closeTracker.recordErrorLocation(this, flowInfo.nullStatus(previousTrackerBinding));
59
		}
60
		FakedTrackingVariable.handleResourceAssignment(flowInfo, this, this.expression, local, previousTrackerBinding);
61
	}
62
	int nullStatus = this.expression.nullStatus(flowInfo);
71
	int nullStatus = this.expression.nullStatus(flowInfo);
63
	if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
72
	if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
64
		if (nullStatus == FlowInfo.NULL) {
73
		if (nullStatus == FlowInfo.NULL) {
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java (-45 / +360 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2011 GK Software AG and others.
2
 * Copyright (c) 2011, 2012 GK Software AG and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 15-21 Link Here
15
import java.util.Map;
15
import java.util.Map;
16
import java.util.Map.Entry;
16
import java.util.Map.Entry;
17
17
18
import org.eclipse.jdt.core.compiler.CharOperation;
19
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
18
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
20
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
19
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
21
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
20
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
Lines 48-67 Link Here
48
	private static final int CLOSED_IN_NESTED_METHOD = 4;
47
	private static final int CLOSED_IN_NESTED_METHOD = 4;
49
	// a location independent issue has been reported already against this resource:
48
	// a location independent issue has been reported already against this resource:
50
	private static final int REPORTED = 8;
49
	private static final int REPORTED = 8;
51
	
50
	// a resource is wrapped in another resource:
51
	private static final int WRAPPED = 16;
52
53
	private static final int DOUBT_MASK = CLOSE_SEEN | PASSED_TO_OUTSIDE | CLOSED_IN_NESTED_METHOD | REPORTED; // not WRAPPED
54
52
	/**
55
	/**
53
	 * Bitset of {@link #CLOSE_SEEN}, {@link #PASSED_TO_OUTSIDE}, {@link #CLOSED_IN_NESTED_METHOD} and {@link #REPORTED}.
56
	 * Bitset of {@link #CLOSE_SEEN}, {@link #PASSED_TO_OUTSIDE}, {@link #CLOSED_IN_NESTED_METHOD}, {@link #REPORTED} and {@link #WRAPPED}.
54
	 */
57
	 */
55
	private int globalClosingState = 0;
58
	private int globalClosingState = 0;
56
59
60
	public LocalVariableBinding originalBinding; // the real local being tracked, can be null for preliminary track vars for allocation expressions
61
	
62
	public FakedTrackingVariable innerTracker; // chained tracking variable of a chained (wrapped) resource
63
57
	MethodScope methodScope; // designates the method declaring this variable
64
	MethodScope methodScope; // designates the method declaring this variable
58
	
59
	public LocalVariableBinding originalBinding; // the real local being tracked
60
	
61
	HashMap recordedLocations; // initially null, ASTNode -> Integer 
62
65
66
	private HashMap recordedLocations; // initially null, ASTNode -> Integer
63
67
64
	public FakedTrackingVariable(LocalVariableBinding original, Statement location) {
68
	// temporary storage while analyzing "res = new Res();":
69
	private ASTNode currentAssignment; // temporarily store the assignment as the location for error reporting
70
71
	public FakedTrackingVariable(LocalVariableBinding original, ASTNode location) {
65
		super(original.name, location.sourceStart, location.sourceEnd);
72
		super(original.name, location.sourceStart, location.sourceEnd);
66
		this.type = new SingleTypeReference(
73
		this.type = new SingleTypeReference(
67
				TypeConstants.OBJECT,
74
				TypeConstants.OBJECT,
Lines 69-74 Link Here
69
		this.methodScope = original.declaringScope.methodScope();
76
		this.methodScope = original.declaringScope.methodScope();
70
		this.originalBinding = original;
77
		this.originalBinding = original;
71
		resolve(original.declaringScope);
78
		resolve(original.declaringScope);
79
	}
80
81
	/* Create an unassigned tracking variable while analyzing an allocation expression: */
82
	private FakedTrackingVariable(BlockScope scope, ASTNode location) {
83
		super("<unassigned Closeable value>".toCharArray(), location.sourceStart, location.sourceEnd); //$NON-NLS-1$
84
		this.type = new SingleTypeReference(
85
				TypeConstants.OBJECT,
86
				((long)this.sourceStart <<32)+this.sourceEnd);
87
		this.methodScope = scope.methodScope();
88
		this.originalBinding = null;
89
		resolve(scope);
72
	}
90
	}
73
	
91
	
74
	public void generateCode(BlockScope currentScope, CodeStream codeStream)
92
	public void generateCode(BlockScope currentScope, CodeStream codeStream)
Lines 88-95 Link Here
88
	}
106
	}
89
107
90
	/**
108
	/**
91
	 * If expression resolves to a local variable binding of type AutoCloseable,
109
	 * If expression resolves to a value of type AutoCloseable answer the variable that tracks closing of that local.
92
	 * answer the variable that tracks closing of that local, creating it if needed.
110
	 * Covers two cases:
111
	 * <ul>
112
	 * <li>value is a local variable reference, create tracking variable it if needed.
113
	 * <li>value is an allocation expression, return a preliminary tracking variable if set.
114
	 * </ul>
93
	 * @param expression
115
	 * @param expression
94
	 * @return a new {@link FakedTrackingVariable} or null.
116
	 * @return a new {@link FakedTrackingVariable} or null.
95
	 */
117
	 */
Lines 107-157 Link Here
107
				Statement location = local.declaration;
129
				Statement location = local.declaration;
108
				return local.closeTracker = new FakedTrackingVariable(local, location);
130
				return local.closeTracker = new FakedTrackingVariable(local, location);
109
			}
131
			}
110
		}
132
		} else if (expression instanceof AllocationExpression) {
133
			// return any preliminary tracking variable from analyseCloseableAllocation 
134
			return ((AllocationExpression) expression).closeTracker;
135
		}		
111
		return null;
136
		return null;
112
	}
137
	}
113
138
114
	/** if 'invocationSite' is a call to close() that has a registered tracking variable, answer that variable's binding. */
139
	/**
115
	public static LocalVariableBinding getTrackerForCloseCall(ASTNode invocationSite) {
140
	 * Before analyzing an assignment of this shape: <code>singleName = new Allocation()</code>
116
		if (invocationSite instanceof MessageSend) {
141
	 * connect any tracking variable of the LHS with the allocation on the RHS.
117
			MessageSend send = (MessageSend) invocationSite;
142
	 * Also the assignment is temporarily stored in the tracking variable in case we need to
118
			if (CharOperation.equals(TypeConstants.CLOSE, send.selector) && send.receiver instanceof SingleNameReference) {
143
	 * report errors because the assignment leaves the old LHS value unclosed.
119
				Binding receiverBinding = ((SingleNameReference)send.receiver).binding;
144
	 * In this case the assignment should be used as the error location.
120
				if (receiverBinding instanceof LocalVariableBinding) {
145
	 * 
121
					FakedTrackingVariable trackingVariable = ((LocalVariableBinding)receiverBinding).closeTracker;
146
	 * @param location the assignment/local declaration being analyzed
122
					if (trackingVariable != null)
147
	 * @param local the local variable being assigned to
123
						return trackingVariable.binding;
148
	 * @param rhs the rhs of the assignment resp. the initialization of the local variable declaration.
124
				}
149
	 */
150
	public static void preConnectTrackerAcrossAssignment(ASTNode location, LocalVariableBinding local, Expression rhs) {
151
		FakedTrackingVariable closeTracker = null;
152
		if (rhs instanceof AllocationExpression) {
153
			closeTracker = local.closeTracker;
154
			if (closeTracker == null) {
155
				if (isAutoCloseable(rhs.resolvedType)) {
156
					closeTracker = new FakedTrackingVariable(local, location);
157
				}					
158
			}
159
			if (closeTracker != null) {
160
				closeTracker.currentAssignment = location;
161
				((AllocationExpression)rhs).closeTracker = closeTracker;
125
			}
162
			}
126
		}
163
		}
127
		return null;
164
	}
165
166
	/** 
167
	 * Compute/assign a tracking variable for a freshly allocated closeable value, using information from our white lists.
168
	 * See  Bug 358903 - Filter practically unimportant resource leak warnings 
169
	 */
170
	public static void analyseCloseableAllocation(BlockScope scope, FlowInfo flowInfo, AllocationExpression allocation) {
171
		// client has checked that the resolvedType is an AutoCloseable, hence the following cast is safe:
172
		if (((ReferenceBinding)allocation.resolvedType).hasTypeBit(TypeIds.BitResourceFreeCloseable)) {
173
			// remove unnecessary attempts (closeable is not relevant)
174
			if (allocation.closeTracker != null) {
175
				scope.removeTrackingVar(allocation.closeTracker);
176
				allocation.closeTracker = null;
177
			}
178
		} else if (((ReferenceBinding)allocation.resolvedType).hasTypeBit(TypeIds.BitWrapperCloseable)) {
179
			if (allocation.arguments != null &&  allocation.arguments.length > 0) {
180
				// find the wrapped resource represented by its tracking var:
181
				FakedTrackingVariable innerTracker = analyseCloseableAllocationArgument(scope, flowInfo, allocation, allocation.arguments[0]);
182
				if (innerTracker != null) {
183
					if (innerTracker == allocation.closeTracker)
184
						return; // self wrap (res = new Res(res)) -> neither change (here) nor remove (below)
185
					if (allocation.closeTracker == null) {
186
						allocation.closeTracker = new FakedTrackingVariable(scope, allocation); // no local available, closeable is unassigned
187
					}
188
					allocation.closeTracker.innerTracker = innerTracker;
189
					innerTracker.globalClosingState |= WRAPPED;
190
					flowInfo.markAsDefinitelyNull(allocation.closeTracker.binding);
191
					return; // keep chaining wrapper
192
				}
193
			}
194
			// remove unnecessary attempts (wrapper has no relevant inner)
195
			if (allocation.closeTracker != null) {
196
				scope.removeTrackingVar(allocation.closeTracker);
197
				allocation.closeTracker = null;
198
			}
199
		} else { // regular resource
200
			FakedTrackingVariable presetTracker = allocation.closeTracker;
201
			if (presetTracker != null && presetTracker.originalBinding != null) {
202
				int closeStatus = flowInfo.nullStatus(presetTracker.binding);
203
				if (closeStatus != FlowInfo.NON_NULL
204
						&& !flowInfo.isDefinitelyNull(presetTracker.originalBinding)
205
						&& !(presetTracker.currentAssignment instanceof LocalDeclaration))
206
					allocation.closeTracker.recordErrorLocation(presetTracker.currentAssignment, closeStatus);
207
			} else {
208
				allocation.closeTracker = new FakedTrackingVariable(scope, allocation); // no local available, closeable is unassigned
209
			}
210
			flowInfo.markAsDefinitelyNull(allocation.closeTracker.binding);
211
		}
212
	}
213
214
	/** Find an existing tracking variable for the argument of an allocation for a resource wrapper. */
215
	public static FakedTrackingVariable analyseCloseableAllocationArgument(BlockScope scope, FlowInfo flowInfo, AllocationExpression allocation, Expression arg)
216
	{
217
		while (arg instanceof Assignment) {
218
			Assignment assign = (Assignment)arg;
219
			LocalVariableBinding innerLocal = assign.localVariableBinding();
220
			if (innerLocal != null) {
221
				// nested assignment has already been processed
222
				return innerLocal.closeTracker;
223
			} else {
224
				arg = assign.expression; // unwrap assignment and fall through
225
			}
226
		}
227
		if (arg instanceof SingleNameReference) {
228
			// is allocation arg a reference to an existing closeable?
229
			LocalVariableBinding local = arg.localVariableBinding();
230
			if (local != null) {
231
				return local.closeTracker;
232
			}
233
		} else if (arg instanceof AllocationExpression && arg.resolvedType instanceof ReferenceBinding) {
234
			// nested allocation
235
			return ((AllocationExpression)arg).closeTracker;
236
		}
237
		return null; // not a tracked expression
128
	}
238
	}
129
239
130
	/** 
240
	/** 
131
	 * Check if the rhs of an assignment or local declaration is an (Auto)Closeable.
241
	 * Check if the rhs of an assignment or local declaration is an (Auto)Closeable.
132
	 * If so create or re-use a tracking variable, and wire and initialize everything. 
242
	 * If so create or re-use a tracking variable, and wire and initialize everything.
243
	 * @param upstreamInfo info without analysis of the rhs, use this to determine the status of a resource being disconnected
244
	 * @param flowInfo info with analysis of the rhs, use this for recording resource status because this will be passed downstream
245
	 * @param location where to report warnigs/errors against
246
	 * @param rhs the right hand side of the assignment, this expression is to be analyzed.
247
	 *			The caller has already checked that the rhs is either of a closeable type or null.
248
	 * @param local the local variable into which the rhs is being assigned
133
	 */
249
	 */
134
	public static void handleResourceAssignment(FlowInfo flowInfo, Statement location, Expression rhs, LocalVariableBinding local,
250
	public static void handleResourceAssignment(FlowInfo upstreamInfo, FlowInfo flowInfo, ASTNode location, Expression rhs, LocalVariableBinding local)
135
				LocalVariableBinding previousTrackerBinding) 
136
	{
251
	{
137
		if (isAutoCloseable(rhs.resolvedType)) {
252
		// does the LHS (local) already have a tracker, indicating we may leak a resource by the assignment?
253
		FakedTrackingVariable previousTracker = null;
254
		FakedTrackingVariable disconnectedTracker = null;
255
		if (local.closeTracker != null) {
256
			// assigning to a variable already holding an AutoCloseable, has it been closed before?
257
			previousTracker = local.closeTracker;
258
			int nullStatus = upstreamInfo.nullStatus(local);
259
			if (nullStatus != FlowInfo.NULL && nullStatus != FlowInfo.UNKNOWN) // only if previous value may be relevant
260
				disconnectedTracker = previousTracker; // report error below, unless we have a self-wrap assignment
261
		}
262
263
		if (rhs.resolvedType != TypeBinding.NULL) {
138
			// new value is AutoCloseable, start tracking, possibly re-using existing tracker var:
264
			// new value is AutoCloseable, start tracking, possibly re-using existing tracker var:
139
	
140
			FakedTrackingVariable rhsTrackVar = getCloseTrackingVariable(rhs);
265
			FakedTrackingVariable rhsTrackVar = getCloseTrackingVariable(rhs);
141
			if (rhsTrackVar != null) {								// 1. share tracking variable with RHS?
266
			if (rhsTrackVar != null) {								// 1. if RHS has a tracking variable...
142
				local.closeTracker = rhsTrackVar;
267
				if (local.closeTracker == null) {
143
				// keep null-status unchanged across this assignment
268
					// null shouldn't occur but let's play safe
144
			} else if (previousTrackerBinding != null) {			// 2. re-use tracking variable from the LHS?
269
					if (rhsTrackVar.originalBinding != null)
145
				// re-assigning from a fresh, mark as not-closed again:
270
						local.closeTracker = rhsTrackVar;			//		a.: let fresh LHS share it 
146
				flowInfo.markAsDefinitelyNull(previousTrackerBinding);
271
				} else {
272
					if (rhsTrackVar == disconnectedTracker && rhs instanceof AllocationExpression)
273
						return; 									// 		b.: self wrapper: res = new Wrap(res); -> done!
274
					local.closeTracker = rhsTrackVar;				//		c.: conflicting LHS and RHS, proceed with recordErrorLocation below
275
				}
276
				// keep close-status of RHS unchanged across this assignment
277
			} else if (previousTracker != null) {					// 2. re-use tracking variable from the LHS?
278
				// re-assigning from a fresh value, mark as not-closed again:
279
				flowInfo.markAsDefinitelyNull(previousTracker.binding);
280
				local.closeTracker = analyseCloseableExpression(flowInfo, local, location, rhs, previousTracker);
147
			} else {												// 3. no re-use, create a fresh tracking variable:
281
			} else {												// 3. no re-use, create a fresh tracking variable:
148
				local.closeTracker = new FakedTrackingVariable(local, location);
282
				rhsTrackVar = analyseCloseableExpression(flowInfo, local, location, rhs, null);
149
				// a fresh resource, mark as not-closed:
283
				if (rhsTrackVar != null) {
150
				flowInfo.markAsDefinitelyNull(local.closeTracker.binding);
284
					local.closeTracker = rhsTrackVar;
285
					// a fresh resource, mark as not-closed:
286
					if ((rhsTrackVar.globalClosingState & PASSED_TO_OUTSIDE) == 0)
287
						flowInfo.markAsDefinitelyNull(rhsTrackVar.binding);
151
// TODO(stephan): this might be useful, but I could not find a test case for it: 
288
// TODO(stephan): this might be useful, but I could not find a test case for it: 
152
//				if (flowContext.initsOnFinally != null)
289
//					if (flowContext.initsOnFinally != null)
153
//					flowContext.initsOnFinally.markAsDefinitelyNonNull(trackerBinding);
290
//						flowContext.initsOnFinally.markAsDefinitelyNonNull(trackerBinding);
291
				}
154
			}
292
			}
293
		}
294
295
		if (disconnectedTracker != null)
296
			disconnectedTracker.recordErrorLocation(location, upstreamInfo.nullStatus(disconnectedTracker.binding));
297
	}
298
	/**
299
	 * Analyze structure of a closeable expression, matching (chained) resources against our white lists.
300
	 * @param flowInfo where to record close status
301
	 * @param local local variable to which the closeable is being assigned
302
	 * @param location where to flag errors/warnings against
303
	 * @param expression expression to be analyzed
304
	 * @param previousTracker when analyzing a re-assignment we may already have a tracking variable for local,
305
	 *  		which we should then re-use
306
	 * @return a tracking variable associated with local or null if no need to track
307
	 */
308
	private static FakedTrackingVariable analyseCloseableExpression(FlowInfo flowInfo, LocalVariableBinding local, 
309
									ASTNode location, Expression expression, FakedTrackingVariable previousTracker) 
310
	{
311
		// unwrap uninteresting nodes:
312
		while (true) {
313
			if (expression instanceof Assignment)
314
				expression = ((Assignment)expression).expression;
315
			else if (expression instanceof CastExpression)
316
				expression = ((CastExpression) expression).expression;
317
			else
318
				break;
319
		}
320
321
		// analyze by node type:
322
		if (expression instanceof AllocationExpression) {
323
			// allocation expressions already have their tracking variables analyzed by analyseCloseableAllocation(..)
324
			FakedTrackingVariable tracker = ((AllocationExpression) expression).closeTracker;
325
			if (tracker != null && tracker.originalBinding == null) {
326
				// tracker without original binding (unassigned closeable) shouldn't reach here but let's play safe
327
				return null;
328
			}
329
			return tracker;
330
		} else if (expression instanceof MessageSend 
331
				|| expression instanceof ArrayReference) 
332
		{
333
			// we *might* be responsible for the resource obtained
334
			FakedTrackingVariable tracker = new FakedTrackingVariable(local, location);
335
			tracker.globalClosingState |= PASSED_TO_OUTSIDE;
336
			flowInfo.markPotentiallyNullBit(tracker.binding);
337
			return tracker;			
338
		} else if (expression instanceof FieldReference 
339
				|| expression instanceof QualifiedNameReference) 
340
		{
341
			// responsibility for this resource probably lies at a higher level
342
			FakedTrackingVariable tracker = new FakedTrackingVariable(local, location);
343
			tracker.globalClosingState |= PASSED_TO_OUTSIDE;
344
			flowInfo.markPotentiallyNonNullBit(tracker.binding);
345
			return tracker;			
346
		}
347
348
		if (expression.resolvedType instanceof ReferenceBinding) {
349
			ReferenceBinding resourceType = (ReferenceBinding) expression.resolvedType;
350
			if (resourceType.hasTypeBit(TypeIds.BitResourceFreeCloseable)) {
351
				// (a) resource-free closeable: -> null
352
				return null;
353
			}
354
		}
355
		if (local.closeTracker != null)
356
			// (c): inner has already been analyzed: -> re-use track var
357
			return local.closeTracker;
358
		return new FakedTrackingVariable(local, location);
359
	}
360
361
	public static void cleanUpAfterAssignment(BlockScope currentScope, int lhsBits, Expression expression) {
362
		// remove all remaining track vars with no original binding
363
364
		// unwrap uninteresting nodes:
365
		while (true) {
366
			if (expression instanceof Assignment)
367
				expression = ((Assignment)expression).expression;
368
			else if (expression instanceof CastExpression)
369
				expression = ((CastExpression) expression).expression;
370
			else
371
				break;
372
		}
373
		if (expression instanceof AllocationExpression) {
374
			FakedTrackingVariable tracker = ((AllocationExpression) expression).closeTracker;
375
			if (tracker != null && tracker.originalBinding == null) {
376
				currentScope.removeTrackingVar(tracker);
377
				((AllocationExpression) expression).closeTracker = null;
378
			}
379
		} else {
380
			// assignment passing a local into a field?
381
			LocalVariableBinding local = expression.localVariableBinding();
382
			if (local != null && local.closeTracker != null && ((lhsBits & Binding.FIELD) != 0))
383
				currentScope.removeTrackingVar(local.closeTracker);
155
		}
384
		}
156
	}
385
	}
157
386
Lines 159-164 Link Here
159
	public static boolean isAutoCloseable(TypeBinding typeBinding) {
388
	public static boolean isAutoCloseable(TypeBinding typeBinding) {
160
		return typeBinding instanceof ReferenceBinding
389
		return typeBinding instanceof ReferenceBinding
161
			&& ((ReferenceBinding)typeBinding).hasTypeBit(TypeIds.BitAutoCloseable|TypeIds.BitCloseable);
390
			&& ((ReferenceBinding)typeBinding).hasTypeBit(TypeIds.BitAutoCloseable|TypeIds.BitCloseable);
391
	}
392
393
	public int findMostSpecificStatus(FlowInfo flowInfo, BlockScope currentScope, BlockScope locationScope) {
394
		int status = FlowInfo.UNKNOWN;
395
		FakedTrackingVariable currentTracker = this;
396
		// loop as to consider wrappers (per white list) encapsulating an inner resource.
397
		while (currentTracker != null) {
398
			LocalVariableBinding currentVar = currentTracker.binding;
399
			int currentStatus = getNullStatusAggressively(currentVar, flowInfo);
400
			if (locationScope != null) // only check at method exit points
401
				currentStatus = mergeCloseStatus(locationScope, currentStatus, currentVar, currentScope);
402
			if (currentStatus == FlowInfo.NON_NULL) {
403
				status = currentStatus;
404
				break; // closed -> stop searching
405
			} else if (status == FlowInfo.NULL || status == FlowInfo.UNKNOWN) {
406
				status = currentStatus; // improved although not yet safe -> keep searching for better
407
			}
408
			currentTracker = currentTracker.innerTracker;
409
		}
410
		return status;
411
	}
412
413
	/**
414
	 * Get the null status looking even into unreachable flows
415
	 * @param local
416
	 * @param flowInfo
417
	 * @return one of the constants FlowInfo.{NULL,POTENTIALLY_NULL,POTENTIALLY_NON_NULL,NON_NULL}.
418
	 */
419
	private int getNullStatusAggressively(LocalVariableBinding local, FlowInfo flowInfo) {
420
		int reachMode = flowInfo.reachMode();
421
		int status = 0;
422
		try {
423
			// unreachable flowInfo is too shy in reporting null-issues, temporarily forget reachability:
424
			if (reachMode != FlowInfo.REACHABLE)
425
				flowInfo.tagBits &= ~FlowInfo.UNREACHABLE;
426
			status = flowInfo.nullStatus(local);
427
		} finally {
428
			// reset
429
			flowInfo.tagBits |= reachMode;
430
		}
431
		// at this point some combinations are not useful so flatten to a single bit:
432
		if ((status & FlowInfo.NULL) != 0) {
433
			if ((status & (FlowInfo.NON_NULL | FlowInfo.POTENTIALLY_NON_NULL)) != 0)
434
				return FlowInfo.POTENTIALLY_NULL; 	// null + doubt = pot null
435
			return FlowInfo.NULL;
436
		} else if ((status & FlowInfo.NON_NULL) != 0) {
437
			if ((status & FlowInfo.POTENTIALLY_NULL) != 0)
438
				return FlowInfo.POTENTIALLY_NULL;	// non-null + doubt = pot null
439
			return FlowInfo.NON_NULL;
440
		} else if ((status & FlowInfo.POTENTIALLY_NULL) != 0)
441
			return FlowInfo.POTENTIALLY_NULL;
442
		return status;
443
	}
444
445
	public int mergeCloseStatus(BlockScope currentScope, int status, LocalVariableBinding local, BlockScope outerScope) {
446
		// get the most suitable null status representing whether resource 'binding' has been closed
447
		// start at 'currentScope' and potentially travel out until 'outerScope'
448
		// at each scope consult any recorded 'finallyInfo'.
449
		if (status != FlowInfo.NON_NULL) {
450
			if (currentScope.finallyInfo != null) {
451
				int finallyStatus = currentScope.finallyInfo.nullStatus(local);
452
				if (finallyStatus == FlowInfo.NON_NULL)
453
					return finallyStatus;
454
				if (finallyStatus != FlowInfo.NULL) // neither is NON_NULL, but not both are NULL => call it POTENTIALLY_NULL
455
					status = FlowInfo.POTENTIALLY_NULL;
456
			}
457
			if (currentScope != outerScope && currentScope.parent instanceof BlockScope)
458
				return mergeCloseStatus(((BlockScope) currentScope.parent), status, local, outerScope);
459
		}
460
		return status;
162
	}
461
	}
163
462
164
	/** Mark that this resource is closed locally. */
463
	/** Mark that this resource is closed locally. */
Lines 180-188 Link Here
180
	 * (as argument to a method/ctor call or as a return value from the current method), 
479
	 * (as argument to a method/ctor call or as a return value from the current method), 
181
	 * and thus should be considered as potentially closed.
480
	 * and thus should be considered as potentially closed.
182
	 */
481
	 */
183
	public static FlowInfo markPassedToOutside(BlockScope scope, Expression expression, FlowInfo flowInfo) {
482
	public static FlowInfo markPassedToOutside(BlockScope scope, Expression expression, FlowInfo flowInfo, TypeBinding allocatedType) {	
483
		if ((allocatedType instanceof ReferenceBinding) // only set when called from AllocationExpression
484
				&& ((ReferenceBinding) allocatedType).hasTypeBit(TypeIds.BitWrapperCloseable))
485
			return flowInfo; // allocation of wrapped closeables is analyzed specially
486
		
184
		FakedTrackingVariable trackVar = getCloseTrackingVariable(expression);
487
		FakedTrackingVariable trackVar = getCloseTrackingVariable(expression);
185
		if (trackVar != null) {
488
		if (trackVar != null) {
489
			if (trackVar.originalBinding == null) {
490
				// an allocation that never was assigned to a local variable -> drop it completely as we're not responsible
491
				scope.removeTrackingVar(trackVar);
492
				return flowInfo;
493
			}
186
			trackVar.globalClosingState |= PASSED_TO_OUTSIDE;
494
			trackVar.globalClosingState |= PASSED_TO_OUTSIDE;
187
			if (scope.methodScope() != trackVar.methodScope)
495
			if (scope.methodScope() != trackVar.methodScope)
188
				trackVar.globalClosingState |= CLOSED_IN_NESTED_METHOD;
496
				trackVar.globalClosingState |= CLOSED_IN_NESTED_METHOD;
Lines 201-209 Link Here
201
	}
509
	}
202
510
203
	public boolean reportRecordedErrors(Scope scope) {
511
	public boolean reportRecordedErrors(Scope scope) {
204
		if (this.globalClosingState == 0) {
512
		FakedTrackingVariable current = this;
205
			reportError(scope.problemReporter(), null, FlowInfo.NULL);
513
		while ((current.globalClosingState & DOUBT_MASK) == 0) {
206
			return true;
514
			current = current.innerTracker;
515
			if (current == null) {
516
				// no relevant state found -> report:
517
				reportError(scope.problemReporter(), null, FlowInfo.NULL);
518
				return true;
519
			}
207
		}
520
		}
208
		boolean hasReported = false;
521
		boolean hasReported = false;
209
		if (this.recordedLocations != null) {
522
		if (this.recordedLocations != null) {
Lines 218-223 Link Here
218
	}
531
	}
219
	
532
	
220
	public void reportError(ProblemReporter problemReporter, ASTNode location, int nullStatus) {
533
	public void reportError(ProblemReporter problemReporter, ASTNode location, int nullStatus) {
534
		if ((this.globalClosingState & WRAPPED) != 0)
535
			return;
221
		if (nullStatus == FlowInfo.NULL) {
536
		if (nullStatus == FlowInfo.NULL) {
222
			if ((this.globalClosingState & CLOSED_IN_NESTED_METHOD) != 0)
537
			if ((this.globalClosingState & CLOSED_IN_NESTED_METHOD) != 0)
223
				problemReporter.potentiallyUnclosedCloseable(this, location);
538
				problemReporter.potentiallyUnclosedCloseable(this, location);
Lines 225-231 Link Here
225
				problemReporter.unclosedCloseable(this, location);
540
				problemReporter.unclosedCloseable(this, location);
226
		} else if (nullStatus == FlowInfo.POTENTIALLY_NULL) {
541
		} else if (nullStatus == FlowInfo.POTENTIALLY_NULL) {
227
			problemReporter.potentiallyUnclosedCloseable(this, location);
542
			problemReporter.potentiallyUnclosedCloseable(this, location);
228
		}		
543
		}
229
	}
544
	}
230
545
231
	public void reportExplicitClosing(ProblemReporter problemReporter) {
546
	public void reportExplicitClosing(ProblemReporter problemReporter) {
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java (-2 / +18 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 13-18 Link Here
13
 *							bug 335093 - [compiler][null] minimal hook for future null annotation support
13
 *							bug 335093 - [compiler][null] minimal hook for future null annotation support
14
 *							bug 349326 - [1.7] new warning for missing try-with-resources
14
 *							bug 349326 - [1.7] new warning for missing try-with-resources
15
 *							bug 186342 - [compiler][null] Using annotations for null checking
15
 *							bug 186342 - [compiler][null] Using annotations for null checking
16
 *							bug 358903 - Filter practically unimportant resource leak warnings
16
 *******************************************************************************/
17
 *******************************************************************************/
17
package org.eclipse.jdt.internal.compiler.ast;
18
package org.eclipse.jdt.internal.compiler.ast;
18
19
Lines 74-84 Link Here
74
		this.initialization.checkNPE(currentScope, flowContext, flowInfo);
75
		this.initialization.checkNPE(currentScope, flowContext, flowInfo);
75
	}
76
	}
76
	
77
	
78
	FlowInfo preInitInfo = null;
79
	boolean shouldAnalyseResource = this.binding != null 
80
			&& flowInfo.reachMode() == FlowInfo.REACHABLE 
81
			&& FakedTrackingVariable.isAutoCloseable(this.initialization.resolvedType);
82
	if (shouldAnalyseResource) {
83
		preInitInfo = flowInfo.unconditionalCopy();
84
		// analysis of resource leaks needs additional context while analyzing the RHS:
85
		FakedTrackingVariable.preConnectTrackerAcrossAssignment(this, this.binding, this.initialization);
86
	}
87
77
	flowInfo =
88
	flowInfo =
78
		this.initialization
89
		this.initialization
79
			.analyseCode(currentScope, flowContext, flowInfo)
90
			.analyseCode(currentScope, flowContext, flowInfo)
80
			.unconditionalInits();
91
			.unconditionalInits();
81
	FakedTrackingVariable.handleResourceAssignment(flowInfo, this, this.initialization, this.binding, null);
92
93
	if (shouldAnalyseResource)
94
		FakedTrackingVariable.handleResourceAssignment(preInitInfo, flowInfo, this, this.initialization, this.binding);
95
	else
96
		FakedTrackingVariable.cleanUpAfterAssignment(currentScope, Binding.LOCAL, this.initialization);
97
82
	int nullStatus = this.initialization.nullStatus(flowInfo);
98
	int nullStatus = this.initialization.nullStatus(flowInfo);
83
	if (!flowInfo.isDefinitelyAssigned(this.binding)){// for local variable debug attributes
99
	if (!flowInfo.isDefinitelyAssigned(this.binding)){// for local variable debug attributes
84
		this.bits |= FirstAssignmentToLocal;
100
		this.bits |= FirstAssignmentToLocal;
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java (-3 / +4 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 12-17 Link Here
12
 *								bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
12
 *								bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
13
 *								bug 349326 - [1.7] new warning for missing try-with-resources
13
 *								bug 349326 - [1.7] new warning for missing try-with-resources
14
 *								bug 186342 - [compiler][null] Using annotations for null checking
14
 *								bug 186342 - [compiler][null] Using annotations for null checking
15
 *								bug 358903 - Filter practically unimportant resource leak warnings
15
 *******************************************************************************/
16
 *******************************************************************************/
16
package org.eclipse.jdt.internal.compiler.ast;
17
package org.eclipse.jdt.internal.compiler.ast;
17
18
Lines 96-104 Link Here
96
			if ((this.arguments[i].implicitConversion & TypeIds.UNBOXING) != 0) {
97
			if ((this.arguments[i].implicitConversion & TypeIds.UNBOXING) != 0) {
97
				this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
98
				this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
98
			}
99
			}
99
			// if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.)
100
			flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo);
101
			flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
100
			flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
101
			// if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.)
102
			flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo, null);
102
		}
103
		}
103
		analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments);
104
		analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments);
104
	}
105
	}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java (-2 / +3 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 11-16 Link Here
11
 *     							bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
11
 *     							bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
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 358903 - Filter practically unimportant resource leak warnings
14
 *******************************************************************************/
15
 *******************************************************************************/
15
package org.eclipse.jdt.internal.compiler.ast;
16
package org.eclipse.jdt.internal.compiler.ast;
16
17
Lines 81-87 Link Here
81
		if (this.arguments != null) {
82
		if (this.arguments != null) {
82
			for (int i = 0, count = this.arguments.length; i < count; i++) {
83
			for (int i = 0, count = this.arguments.length; i < count; i++) {
83
				// if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.)
84
				// if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.)
84
				flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo);
85
				flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo, null);
85
				flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo);
86
				flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo);
86
				if ((this.arguments[i].implicitConversion & TypeIds.UNBOXING) != 0) {
87
				if ((this.arguments[i].implicitConversion & TypeIds.UNBOXING) != 0) {
87
					this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
88
					this.arguments[i].checkNPE(currentScope, flowContext, flowInfo);
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java (-1 / +1 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java (-2 / +3 lines)
Lines 12-17 Link Here
12
 *     							bug 358827 - [1.7] exception analysis for t-w-r spoils null analysis
12
 *     							bug 358827 - [1.7] exception analysis for t-w-r spoils null analysis
13
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
13
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
14
 *     							bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
14
 *     							bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
15
 *								bug 358903 - Filter practically unimportant resource leak warnings
15
 *******************************************************************************/
16
 *******************************************************************************/
16
package org.eclipse.jdt.internal.compiler.ast;
17
package org.eclipse.jdt.internal.compiler.ast;
17
18
Lines 134-140 Link Here
134
			if (resourceBinding.closeTracker != null) {
135
			if (resourceBinding.closeTracker != null) {
135
				// this was false alarm, we don't need to track the resource
136
				// this was false alarm, we don't need to track the resource
136
				this.tryBlock.scope.removeTrackingVar(resourceBinding.closeTracker);
137
				this.tryBlock.scope.removeTrackingVar(resourceBinding.closeTracker);
137
				resourceBinding.closeTracker = null;
138
				// keep the tracking variable in the resourceBinding in order to prevent creating a new one while analyzing the try block
138
			}
139
			}
139
			TypeBinding type = resourceBinding.type;
140
			TypeBinding type = resourceBinding.type;
140
			if (type != null && type.isValidBinding()) {
141
			if (type != null && type.isValidBinding()) {
Lines 276-282 Link Here
276
			if (resourceBinding.closeTracker != null) {
277
			if (resourceBinding.closeTracker != null) {
277
				// this was false alarm, we don't need to track the resource
278
				// this was false alarm, we don't need to track the resource
278
				this.tryBlock.scope.removeTrackingVar(resourceBinding.closeTracker);
279
				this.tryBlock.scope.removeTrackingVar(resourceBinding.closeTracker);
279
				resourceBinding.closeTracker = null;
280
				// keep the tracking variable in the resourceBinding in order to prevent creating a new one while analyzing the try block
280
			} 
281
			} 
281
			TypeBinding type = resourceBinding.type;
282
			TypeBinding type = resourceBinding.type;
282
			if (type != null && type.isValidBinding()) {
283
			if (type != null && type.isValidBinding()) {
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java (-3 / +6 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 11-16 Link Here
11
 *								bug 349326 - [1.7] new warning for missing try-with-resources
11
 *								bug 349326 - [1.7] new warning for missing try-with-resources
12
 *								bug 186342 - [compiler][null] Using annotations for null checking
12
 *								bug 186342 - [compiler][null] Using annotations for null checking
13
 *								bug 364890 - BinaryTypeBinding should use char constants from Util
13
 *								bug 364890 - BinaryTypeBinding should use char constants from Util
14
 *								bug 358903 - Filter practically unimportant resource leak warnings
14
 *******************************************************************************/
15
 *******************************************************************************/
15
package org.eclipse.jdt.internal.compiler.lookup;
16
package org.eclipse.jdt.internal.compiler.lookup;
16
17
Lines 1275-1281 Link Here
1275
			this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations;
1276
			this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations;
1276
		}
1277
		}
1277
	}
1278
	}
1278
	this.typeBits |= this.superclass.typeBits;
1279
	this.typeBits |= (this.superclass.typeBits & TypeIds.InheritableBits);
1280
	if ((this.typeBits & (TypeIds.BitAutoCloseable|TypeIds.BitCloseable)) != 0) // avoid the side-effects of hasTypeBit()! 
1281
		this.typeBits |= applyCloseableWhitelists();
1279
	return this.superclass;
1282
	return this.superclass;
1280
}
1283
}
1281
// NOTE: superInterfaces of binary types are resolved when needed
1284
// NOTE: superInterfaces of binary types are resolved when needed
Lines 1298-1304 Link Here
1298
				this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations;
1301
				this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations;
1299
			}	
1302
			}	
1300
		}
1303
		}
1301
		this.typeBits |= this.superInterfaces[i].typeBits;
1304
		this.typeBits |= (this.superInterfaces[i].typeBits & TypeIds.InheritableBits);
1302
	}
1305
	}
1303
	this.tagBits &= ~TagBits.HasUnresolvedSuperinterfaces;
1306
	this.tagBits &= ~TagBits.HasUnresolvedSuperinterfaces;
1304
	return this.superInterfaces;
1307
	return this.superInterfaces;
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java (-55 / +12 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 10-15 Link Here
10
 *     Stephan Herrmann - Contributions for
10
 *     Stephan Herrmann - Contributions for
11
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
11
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
12
 *								bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
12
 *								bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
13
 *								bug 358903 - Filter practically unimportant resource leak warnings
13
 *******************************************************************************/
14
 *******************************************************************************/
14
package org.eclipse.jdt.internal.compiler.lookup;
15
package org.eclipse.jdt.internal.compiler.lookup;
15
16
Lines 981-986 Link Here
981
}
982
}
982
/** When are no longer interested in this tracking variable - remove it. */
983
/** When are no longer interested in this tracking variable - remove it. */
983
public void removeTrackingVar(FakedTrackingVariable trackingVariable) {
984
public void removeTrackingVar(FakedTrackingVariable trackingVariable) {
985
	if (trackingVariable.innerTracker != null) {
986
		removeTrackingVar(trackingVariable.innerTracker);
987
		trackingVariable.innerTracker = null;
988
	}
984
	if (this.trackingVariables != null)
989
	if (this.trackingVariables != null)
985
		if (this.trackingVariables.remove(trackingVariable))
990
		if (this.trackingVariables.remove(trackingVariable))
986
			return;
991
			return;
Lines 1003-1012 Link Here
1003
		FakedTrackingVariable trackingVar = (FakedTrackingVariable) this.trackingVariables.get(i);
1008
		FakedTrackingVariable trackingVar = (FakedTrackingVariable) this.trackingVariables.get(i);
1004
		if (location != null && trackingVar.originalBinding != null && flowInfo.isDefinitelyNull(trackingVar.originalBinding))
1009
		if (location != null && trackingVar.originalBinding != null && flowInfo.isDefinitelyNull(trackingVar.originalBinding))
1005
			continue; // reporting against a specific location, resource is null at this flow, don't complain
1010
			continue; // reporting against a specific location, resource is null at this flow, don't complain
1006
		int status = getNullStatusAggressively(trackingVar.binding, flowInfo);
1011
		
1007
		// try to improve info if a close() inside finally was observed:
1012
		// compute the most specific null status for this resource,
1008
		if (locationScope != null) // only check at method exit points
1013
		int status = trackingVar.findMostSpecificStatus(flowInfo, this, locationScope);
1009
			status = locationScope.mergeCloseStatus(status, trackingVar.binding, this);
1014
		
1010
		if (status == FlowInfo.NULL) {
1015
		if (status == FlowInfo.NULL) {
1011
			// definitely unclosed: highest priority
1016
			// definitely unclosed: highest priority
1012
			reportResourceLeak(trackingVar, location, status);
1017
			reportResourceLeak(trackingVar, location, status);
Lines 1033-1056 Link Here
1033
			this.locals[i].closeTracker = null;		
1038
			this.locals[i].closeTracker = null;		
1034
		this.trackingVariables = null;
1039
		this.trackingVariables = null;
1035
	}
1040
	}
1036
}
1037
1038
private int mergeCloseStatus(int status, LocalVariableBinding binding, BlockScope outerScope) {
1039
	// get the most suitable null status representing whether resource 'binding' has been closed
1040
	// start at this scope and potentially travel out until 'outerScope'
1041
	// at each scope consult any recorded 'finallyInfo'.
1042
	if (status != FlowInfo.NON_NULL) {
1043
		if (this.finallyInfo != null) {
1044
			int finallyStatus = this.finallyInfo.nullStatus(binding);
1045
			if (finallyStatus == FlowInfo.NON_NULL)
1046
				return finallyStatus;
1047
			if (finallyStatus != FlowInfo.NULL) // neither is NON_NULL, but not both are NULL => call it POTENTIALLY_NULL
1048
				status = FlowInfo.POTENTIALLY_NULL;
1049
		}
1050
		if (this != outerScope && this.parent instanceof BlockScope)
1051
			return ((BlockScope) this.parent).mergeCloseStatus(status, binding, outerScope);
1052
	}
1053
	return status;
1054
}
1041
}
1055
1042
1056
private void reportResourceLeak(FakedTrackingVariable trackingVar, ASTNode location, int nullStatus) {
1043
private void reportResourceLeak(FakedTrackingVariable trackingVar, ASTNode location, int nullStatus) {
Lines 1083-1088 Link Here
1083
	if (this.trackingVariables != null) {
1070
	if (this.trackingVariables != null) {
1084
		for (int i=0; i<this.trackingVariables.size(); i++) {
1071
		for (int i=0; i<this.trackingVariables.size(); i++) {
1085
			FakedTrackingVariable trackingVar = (FakedTrackingVariable) this.trackingVariables.get(i);
1072
			FakedTrackingVariable trackingVar = (FakedTrackingVariable) this.trackingVariables.get(i);
1073
			if (trackingVar.originalBinding == null)
1074
				continue;
1086
			if (   thenFlowInfo.isDefinitelyNonNull(trackingVar.binding)			// closed in then branch
1075
			if (   thenFlowInfo.isDefinitelyNonNull(trackingVar.binding)			// closed in then branch
1087
				&& elseFlowInfo.isDefinitelyNull(trackingVar.originalBinding))		// null in else branch
1076
				&& elseFlowInfo.isDefinitelyNull(trackingVar.originalBinding))		// null in else branch
1088
			{
1077
			{
Lines 1097-1133 Link Here
1097
	}
1086
	}
1098
	if (this.parent instanceof BlockScope)
1087
	if (this.parent instanceof BlockScope)
1099
		((BlockScope) this.parent).correlateTrackingVarsIfElse(thenFlowInfo, elseFlowInfo);
1088
		((BlockScope) this.parent).correlateTrackingVarsIfElse(thenFlowInfo, elseFlowInfo);
1100
}
1101
1102
/**
1103
 * Get the null status looking even into unreachable flows
1104
 * @param local
1105
 * @param flowInfo
1106
 * @return one of the constants FlowInfo.{NULL,POTENTIALLY_NULL,POTENTIALLY_NON_NULL,NON_NULL}.
1107
 */
1108
private int getNullStatusAggressively(LocalVariableBinding local, FlowInfo flowInfo) {
1109
	int reachMode = flowInfo.reachMode();
1110
	int status = 0;
1111
	try {
1112
		// unreachable flowInfo is too shy in reporting null-issues, temporarily forget reachability:
1113
		if (reachMode != FlowInfo.REACHABLE)
1114
			flowInfo.tagBits &= ~FlowInfo.UNREACHABLE;
1115
		status = flowInfo.nullStatus(local);
1116
	} finally {
1117
		// reset
1118
		flowInfo.tagBits |= reachMode;
1119
	}
1120
	// at this point some combinations are not useful so flatten to a single bit:
1121
	if ((status & FlowInfo.NULL) != 0) {
1122
		if ((status & (FlowInfo.NON_NULL | FlowInfo.POTENTIALLY_NON_NULL)) != 0)
1123
			return FlowInfo.POTENTIALLY_NULL; 	// null + doubt = pot null
1124
		return FlowInfo.NULL;
1125
	} else if ((status & FlowInfo.NON_NULL) != 0) {
1126
		if ((status & FlowInfo.POTENTIALLY_NULL) != 0)
1127
			return FlowInfo.POTENTIALLY_NULL;	// non-null + doubt = pot null
1128
		return FlowInfo.NON_NULL;
1129
	} else if ((status & FlowInfo.POTENTIALLY_NULL) != 0)
1130
		return FlowInfo.POTENTIALLY_NULL;
1131
	return status;
1132
}
1089
}
1133
}
1090
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java (-3 / +7 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 12-17 Link Here
12
 *     						Bug 300576 - NPE Computing type hierarchy when compliance doesn't match libraries
12
 *     						Bug 300576 - NPE Computing type hierarchy when compliance doesn't match libraries
13
 *     						Bug 354536 - compiling package-info.java still depends on the order of compilation units
13
 *     						Bug 354536 - compiling package-info.java still depends on the order of compilation units
14
 *     						Bug 349326 - [1.7] new warning for missing try-with-resources
14
 *     						Bug 349326 - [1.7] new warning for missing try-with-resources
15
 *     						Bug 358903 - Filter practically unimportant resource leak warnings
15
 *******************************************************************************/
16
 *******************************************************************************/
16
package org.eclipse.jdt.internal.compiler.lookup;
17
package org.eclipse.jdt.internal.compiler.lookup;
17
18
Lines 909-915 Link Here
909
			} else {
910
			} else {
910
				// only want to reach here when no errors are reported
911
				// only want to reach here when no errors are reported
911
				sourceType.superclass = superclass;
912
				sourceType.superclass = superclass;
912
				sourceType.typeBits |= superclass.typeBits;
913
				sourceType.typeBits |= (superclass.typeBits & TypeIds.InheritableBits);
914
				// further analysis against white lists for the unlikely case we are compiling java.io.*:
915
				if ((sourceType.typeBits & (TypeIds.BitAutoCloseable|TypeIds.BitCloseable)) != 0)
916
					sourceType.typeBits |= sourceType.applyCloseableWhitelists();
913
				return true;
917
				return true;
914
			}
918
			}
915
		}
919
		}
Lines 1025-1031 Link Here
1025
				noProblems &= superInterfaceRef.resolvedType.isValidBinding();
1029
				noProblems &= superInterfaceRef.resolvedType.isValidBinding();
1026
			}
1030
			}
1027
			// only want to reach here when no errors are reported
1031
			// only want to reach here when no errors are reported
1028
			sourceType.typeBits |= superInterface.typeBits;
1032
			sourceType.typeBits |= (superInterface.typeBits & TypeIds.InheritableBits);
1029
			interfaceBindings[count++] = superInterface;
1033
			interfaceBindings[count++] = superInterface;
1030
		}
1034
		}
1031
		// hold onto all correctly resolved superinterfaces
1035
		// hold onto all correctly resolved superinterfaces
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java (-1 / +34 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 10-15 Link Here
10
 *     Stephan Herrmann - Contributions for
10
 *     Stephan Herrmann - Contributions for
11
 *								bug 349326 - [1.7] new warning for missing try-with-resources
11
 *								bug 349326 - [1.7] new warning for missing try-with-resources
12
 *								bug 186342 - [compiler][null] Using annotations for null checking
12
 *								bug 186342 - [compiler][null] Using annotations for null checking
13
 *								bug 358903 - Filter practically unimportant resource leak warnings
13
 *******************************************************************************/
14
 *******************************************************************************/
14
package org.eclipse.jdt.internal.compiler.lookup;
15
package org.eclipse.jdt.internal.compiler.lookup;
15
16
Lines 1469-1472 Link Here
1469
public FieldBinding[] unResolvedFields() {
1470
public FieldBinding[] unResolvedFields() {
1470
	return Binding.NO_FIELDS;
1471
	return Binding.NO_FIELDS;
1471
}
1472
}
1473
1474
/*
1475
 * If a type - known to be a Closeable - is mentioned in one of our white lists
1476
 * answer the typeBit for the white list (BitWrapperCloseable or BitResourceFreeCloseable).
1477
 */
1478
protected int applyCloseableWhitelists() {
1479
	switch (this.compoundName.length) {
1480
		case 3:
1481
			if (CharOperation.equals(TypeConstants.JAVA, this.compoundName[0])) {
1482
				if (CharOperation.equals(TypeConstants.IO, this.compoundName[1])) {
1483
					char[] simpleName = this.compoundName[2];
1484
					int l = TypeConstants.JAVA_IO_WRAPPER_CLOSEABLES.length;
1485
					for (int i = 0; i < l; i++) {
1486
						if (CharOperation.equals(simpleName, TypeConstants.JAVA_IO_WRAPPER_CLOSEABLES[i]))
1487
							return TypeIds.BitWrapperCloseable;
1488
					}
1489
					l = TypeConstants.JAVA_IO_RESOURCE_FREE_CLOSEABLES.length;
1490
					for (int i = 0; i < l; i++) {
1491
						if (CharOperation.equals(simpleName, TypeConstants.JAVA_IO_RESOURCE_FREE_CLOSEABLES[i]))
1492
							return TypeIds.BitResourceFreeCloseable;
1493
					}
1494
				}
1495
			}
1496
			break;
1497
	}
1498
	int l = TypeConstants.OTHER_WRAPPER_CLOSEABLES.length;
1499
	for (int i = 0; i < l; i++) {
1500
		if (CharOperation.equals(this.compoundName, TypeConstants.OTHER_WRAPPER_CLOSEABLES[i]))
1501
			return TypeIds.BitWrapperCloseable;
1502
	}	
1503
	return 0;
1504
}
1472
}
1505
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java (-2 / +31 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 7-13 Link Here
7
 * 
7
 * 
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Stephan Herrmann - Contribution for bug 349326 - [1.7] new warning for missing try-with-resources
10
 *     Stephan Herrmann - Contributions for
11
 *								bug 349326 - [1.7] new warning for missing try-with-resources
12
 *								bug 358903 - Filter practically unimportant resource leak warnings
11
 *******************************************************************************/
13
 *******************************************************************************/
12
package org.eclipse.jdt.internal.compiler.lookup;
14
package org.eclipse.jdt.internal.compiler.lookup;
13
15
Lines 154-159 Link Here
154
	};
156
	};
155
	char[][] JAVA_LANG_AUTOCLOSEABLE =  {JAVA, LANG, "AutoCloseable".toCharArray()}; //$NON-NLS-1$
157
	char[][] JAVA_LANG_AUTOCLOSEABLE =  {JAVA, LANG, "AutoCloseable".toCharArray()}; //$NON-NLS-1$
156
	char[] CLOSE = "close".toCharArray(); //$NON-NLS-1$
158
	char[] CLOSE = "close".toCharArray(); //$NON-NLS-1$
159
	// white lists of closeables:
160
	char[][] JAVA_IO_WRAPPER_CLOSEABLES = new char[][] {
161
		"BufferedInputStream".toCharArray(), //$NON-NLS-1$
162
		"BufferedOutputStream".toCharArray(), //$NON-NLS-1$
163
		"BufferedReader".toCharArray(), //$NON-NLS-1$
164
		"BufferedWriter".toCharArray(), //$NON-NLS-1$
165
		"InputStreamReader".toCharArray(), //$NON-NLS-1$
166
		"PrintWriter".toCharArray(),  //$NON-NLS-1$
167
		"LineNumberReader".toCharArray(), //$NON-NLS-1$
168
		"DataInputStream".toCharArray(), //$NON-NLS-1$
169
		"DataOutputStream".toCharArray(), //$NON-NLS-1$
170
		"ObjectInputStream".toCharArray(), //$NON-NLS-1$
171
		"ObjectOutputStream".toCharArray(), //$NON-NLS-1$
172
		"FilterInputStream".toCharArray(), //$NON-NLS-1$
173
		"FilterOutputStream".toCharArray(), //$NON-NLS-1$
174
	};
175
	char[][][] OTHER_WRAPPER_CLOSEABLES = new char[][][] { // NOTE: if this list should ever grow large we should think of smarter data structure
176
		{JAVA, UTIL, "zip".toCharArray(), "InflaterInputStream".toCharArray()},	 //$NON-NLS-1$ //$NON-NLS-2$
177
	};
178
	char[][] JAVA_IO_RESOURCE_FREE_CLOSEABLES = new char[][] {			
179
		"StringReader".toCharArray(), //$NON-NLS-1$
180
		"StringWriter".toCharArray(), //$NON-NLS-1$
181
		"ByteArrayInputStream".toCharArray(), //$NON-NLS-1$
182
		"ByteArrayOutputStream".toCharArray(), //$NON-NLS-1$
183
		"CharArrayReader".toCharArray(), //$NON-NLS-1$
184
		"CharArrayWriter".toCharArray(), //$NON-NLS-1$
185
	};
157
186
158
	// Constraints for generic type argument inference
187
	// Constraints for generic type argument inference
159
	int CONSTRAINT_EQUAL = 0;		// Actual = Formal
188
	int CONSTRAINT_EQUAL = 0;		// Actual = Formal
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java (-1 / +17 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 11-16 Link Here
11
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
11
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
12
 *     							bug 359362 - FUP of bug 349326: Resource leak on non-Closeable resource
12
 *     							bug 359362 - FUP of bug 349326: Resource leak on non-Closeable resource
13
 *								bug 186342 - [compiler][null] Using annotations for null checking
13
 *								bug 186342 - [compiler][null] Using annotations for null checking
14
 *								bug 358903 - Filter practically unimportant resource leak warnings
14
 *******************************************************************************/
15
 *******************************************************************************/
15
package org.eclipse.jdt.internal.compiler.lookup;
16
package org.eclipse.jdt.internal.compiler.lookup;
16
17
Lines 207-210 Link Here
207
	 * @see ReferenceBinding#hasTypeBit(int)
208
	 * @see ReferenceBinding#hasTypeBit(int)
208
	 */
209
	 */
209
	final int BitCloseable = 2;
210
	final int BitCloseable = 2;
211
	/**
212
	 * Bit for members of a white list:
213
	 * Subtypes of Closeable that wrap another resource without directly holding any OS resources. 
214
	 */
215
	final int BitWrapperCloseable = 4;
216
	/**
217
	 * Bit for members of a white list:
218
	 * Subtypes of Closeable that do not hold an OS resource that needs to be released.
219
	 */
220
	final int BitResourceFreeCloseable = 8;
221
	
222
	/**
223
	 * Set of type bits that should be inherited by any sub types.
224
	 */
225
	final int InheritableBits = BitAutoCloseable | BitCloseable;
210
}
226
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java (-3 / +4 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 11-16 Link Here
11
 *     							bug 282152 - [1.5][compiler] Generics code rejected by Eclipse but accepted by javac
11
 *     							bug 282152 - [1.5][compiler] Generics code rejected by Eclipse but accepted by javac
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 359362 - FUP of bug 349326: Resource leak on non-Closeable resource
13
 *     							bug 359362 - FUP of bug 349326: Resource leak on non-Closeable resource
14
 *								bug 358903 - Filter practically unimportant resource leak warnings
14
 *******************************************************************************/
15
 *******************************************************************************/
15
package org.eclipse.jdt.internal.compiler.lookup;
16
package org.eclipse.jdt.internal.compiler.lookup;
16
17
Lines 316-326 Link Here
316
			// initialize from bounds
317
			// initialize from bounds
317
			this.typeBits = 0;
318
			this.typeBits = 0;
318
			if (this.superclass != null && this.superclass.hasTypeBit(~TypeIds.BitUninitialized))
319
			if (this.superclass != null && this.superclass.hasTypeBit(~TypeIds.BitUninitialized))
319
				this.typeBits |= this.superclass.typeBits;
320
				this.typeBits |= (this.superclass.typeBits & TypeIds.InheritableBits);
320
			if (this.superInterfaces != null)
321
			if (this.superInterfaces != null)
321
				for (int i = 0, l = this.superInterfaces.length; i < l; i++)
322
				for (int i = 0, l = this.superInterfaces.length; i < l; i++)
322
					if (this.superInterfaces[i].hasTypeBit(~TypeIds.BitUninitialized))
323
					if (this.superInterfaces[i].hasTypeBit(~TypeIds.BitUninitialized))
323
						this.typeBits |= this.superInterfaces[i].typeBits;
324
						this.typeBits |= (this.superInterfaces[i].typeBits & TypeIds.InheritableBits);
324
		}
325
		}
325
		return (this.typeBits & bit) != 0;
326
		return (this.typeBits & bit) != 0;
326
	}
327
	}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java (-3 / +4 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2011 IBM Corporation and others.
2
 * Copyright (c) 2005, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 10-15 Link Here
10
 *     Stephan Herrmann - Contribution for
10
 *     Stephan Herrmann - Contribution for
11
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
11
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
12
 *     							bug 359362 - FUP of bug 349326: Resource leak on non-Closeable resource
12
 *     							bug 359362 - FUP of bug 349326: Resource leak on non-Closeable resource
13
 *								bug 358903 - Filter practically unimportant resource leak warnings
13
 *******************************************************************************/
14
 *******************************************************************************/
14
package org.eclipse.jdt.internal.compiler.lookup;
15
package org.eclipse.jdt.internal.compiler.lookup;
15
16
Lines 429-439 Link Here
429
			// initialize from upper bounds
430
			// initialize from upper bounds
430
			this.typeBits = 0;
431
			this.typeBits = 0;
431
			if (this.superclass != null && this.superclass.hasTypeBit(~TypeIds.BitUninitialized))
432
			if (this.superclass != null && this.superclass.hasTypeBit(~TypeIds.BitUninitialized))
432
				this.typeBits |= this.superclass.typeBits;
433
				this.typeBits |= (this.superclass.typeBits & TypeIds.InheritableBits);
433
			if (this.superInterfaces != null)
434
			if (this.superInterfaces != null)
434
				for (int i = 0, l = this.superInterfaces.length; i < l; i++)
435
				for (int i = 0, l = this.superInterfaces.length; i < l; i++)
435
					if (this.superInterfaces[i].hasTypeBit(~TypeIds.BitUninitialized))
436
					if (this.superInterfaces[i].hasTypeBit(~TypeIds.BitUninitialized))
436
						this.typeBits |= this.superInterfaces[i].typeBits;
437
						this.typeBits |= (this.superInterfaces[i].typeBits & TypeIds.InheritableBits);
437
		}
438
		}
438
		return (this.typeBits & bit) != 0;
439
		return (this.typeBits & bit) != 0;
439
	}
440
	}

Return to bug 358903