Bug 68998 - [1.5] NPE in java compiler
Summary: [1.5] NPE in java compiler
Status: RESOLVED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.0   Edit
Hardware: PC Windows 2000
: P3 normal (vote)
Target Milestone: 3.1 M1   Edit
Assignee: Philipe Mulet CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-06-30 08:59 EDT by Igor Fedorenko CLA
Modified: 2005-01-11 11:02 EST (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Igor Fedorenko CLA 2004-06-30 08:59:51 EDT
Latest cheetah from CVS. NullPointerException when a subclass of a generic type
uses protected member field of its parent. This NPE makes java editor unusable
(i.e. cannot save the source). Yet another reason to resolve bug 68586 ;-)

==================================
package test.cheetah;
public class G<E> {
    protected Object o;
}
==================================
package test.cheetah;
public class NG extends G {
    public boolean test() {
        return o == null;
    }
}
==================================

Compiling the second of the two classes results in

!ENTRY org.eclipse.core.runtime 4 2 Jun 30, 2004 08:48:46.830
!MESSAGE Problems occurred when invoking code from plug-in:
"org.eclipse.core.runtime".
!STACK 0
java.lang.NullPointerException
	at
org.eclipse.jdt.internal.compiler.codegen.CodeStream.generateConstant(CodeStream.java:1385)
	at
org.eclipse.jdt.internal.compiler.ast.SingleNameReference.generateCode(SingleNameReference.java:304)
	at
org.eclipse.jdt.internal.compiler.ast.EqualExpression.generateOptimizedNonBooleanEqual(EqualExpression.java:401)
	at
org.eclipse.jdt.internal.compiler.ast.EqualExpression.generateOptimizedBoolean(EqualExpression.java:275)
	at
org.eclipse.jdt.internal.compiler.ast.EqualExpression.generateCode(EqualExpression.java:232)
	at
org.eclipse.jdt.internal.compiler.ast.ReturnStatement.generateCode(ReturnStatement.java:116)
	at
org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.generateCode(AbstractMethodDeclaration.java:214)
	at
org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.generateCode(AbstractMethodDeclaration.java:161)
	at
org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.generateCode(TypeDeclaration.java:555)
	at
org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.generateCode(TypeDeclaration.java:609)
	at
org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration.generateCode(CompilationUnitDeclaration.java:180)
	at org.eclipse.jdt.internal.compiler.Compiler.process(Compiler.java:514)
	at org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:335)
	at
org.eclipse.jdt.internal.core.builder.AbstractImageBuilder.compile(AbstractImageBuilder.java:209)
	at
org.eclipse.jdt.internal.core.builder.AbstractImageBuilder.compile(AbstractImageBuilder.java:159)
	at
org.eclipse.jdt.internal.core.builder.BatchImageBuilder.build(BatchImageBuilder.java:49)
	at org.eclipse.jdt.internal.core.builder.JavaBuilder.buildAll(JavaBuilder.java:212)
	at org.eclipse.jdt.internal.core.builder.JavaBuilder.build(JavaBuilder.java:135)
	at org.eclipse.core.internal.events.BuildManager$2.run(BuildManager.java:564)
	at
org.eclipse.core.internal.runtime.InternalPlatform.run(InternalPlatform.java:615)
	at org.eclipse.core.runtime.Platform.run(Platform.java:747)
	at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:157)
	at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:249)
	at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:202)
	at org.eclipse.core.internal.events.BuildManager$1.run(BuildManager.java:229)
	at
org.eclipse.core.internal.runtime.InternalPlatform.run(InternalPlatform.java:615)
	at org.eclipse.core.runtime.Platform.run(Platform.java:747)
	at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:232)
	at
org.eclipse.core.internal.events.BuildManager.basicBuildLoop(BuildManager.java:268)
	at org.eclipse.core.internal.events.BuildManager.build(BuildManager.java:297)
	at org.eclipse.core.internal.resources.Workspace.build(Workspace.java:198)
	at org.eclipse.ui.actions.GlobalBuildAction$1.run(GlobalBuildAction.java:182)
	at org.eclipse.core.internal.jobs.Worker.run(Worker.java:66)


PS: as a positive side effect of this bug I had to encapsulate all protected
variables :-)
Comment 1 Philipe Mulet CLA 2004-07-01 11:17:28 EDT
Fixed in HEAD. Constant propagation did not handle correctly duality of 
ParameterizedFieldBinding and original FieldBinding.

Added regression test: GenericTypeTest#test216.
Comment 2 Igor Fedorenko CLA 2004-07-01 21:52:31 EDT
Compiling the same code now results in ClassCastException

!ENTRY org.eclipse.jdt.core 4 4 Jul 01, 2004 21:44:21.322
!MESSAGE Exception occurred during problem detection: 
!STACK 0
java.lang.ClassCastException
	at
org.eclipse.jdt.internal.compiler.ast.FieldReference.getConstantFor(FieldReference.java:352)
	at
org.eclipse.jdt.internal.compiler.ast.SingleNameReference.checkFieldAccess(SingleNameReference.java:163)
	at
org.eclipse.jdt.internal.compiler.ast.SingleNameReference.resolveType(SingleNameReference.java:647)
	at
org.eclipse.jdt.internal.compiler.ast.EqualExpression.resolveType(EqualExpression.java:504)
	at
org.eclipse.jdt.internal.compiler.ast.ReturnStatement.resolve(ReturnStatement.java:214)
	at
org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.resolveStatements(AbstractMethodDeclaration.java:395)
	at
org.eclipse.jdt.internal.compiler.ast.MethodDeclaration.resolveStatements(MethodDeclaration.java:134)
	at
org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.resolve(AbstractMethodDeclaration.java:373)
	at
org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:920)
	at
org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:969)
	at
org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration.resolve(CompilationUnitDeclaration.java:280)
	at org.eclipse.jdt.internal.compiler.Compiler.resolve(Compiler.java:564)
	at
org.eclipse.jdt.internal.core.CompilationUnitProblemFinder.process(CompilationUnitProblemFinder.java:176)
	at
org.eclipse.jdt.internal.core.CompilationUnit.buildStructure(CompilationUnit.java:146)
	at org.eclipse.jdt.internal.core.Openable.generateInfos(Openable.java:183)
	at org.eclipse.jdt.internal.core.JavaElement.openWhenClosed(JavaElement.java:572)
	at
org.eclipse.jdt.internal.core.CompilationUnit.makeConsistent(CompilationUnit.java:971)
	at
org.eclipse.jdt.internal.core.ReconcileWorkingCopyOperation.executeOperation(ReconcileWorkingCopyOperation.java:58)
	at
org.eclipse.jdt.internal.core.JavaModelOperation.run(JavaModelOperation.java:700)
	at
org.eclipse.jdt.internal.core.JavaModelOperation.runOperation(JavaModelOperation.java:739)
	at
org.eclipse.jdt.internal.core.CompilationUnit.reconcile(CompilationUnit.java:1097)
	at
org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.reconcile(JavaReconcilingStrategy.java:88)
	at
org.eclipse.jdt.internal.ui.text.java.JavaReconcilingStrategy.reconcile(JavaReconcilingStrategy.java:129)
	at
org.eclipse.jdt.internal.ui.text.CompositeReconcilingStrategy.reconcile(CompositeReconcilingStrategy.java:86)
	at
org.eclipse.jdt.internal.ui.text.JavaCompositeReconcilingStrategy.reconcile(JavaCompositeReconcilingStrategy.java:96)
	at org.eclipse.jface.text.reconciler.MonoReconciler.process(MonoReconciler.java:75)
	at org.eclipse.jdt.internal.ui.text.JavaReconciler.process(JavaReconciler.java:315)
	at
org.eclipse.jface.text.reconciler.AbstractReconciler$BackgroundThread.run(AbstractReconciler.java:204)
Comment 3 Philipe Mulet CLA 2004-07-03 10:21:10 EDT
Igor - are you sure you took the proper fix from HEAD ? Can no longer 
reproduce, and regression test is passing.
Comment 4 Igor Fedorenko CLA 2004-07-03 12:42:52 EDT
Just checked that my org.eclipse.jdt.core is in sync with HEAD and yet I am
getting the ClassCastException. I have two workspaces -- one for cheetah itself
and another for jdk1.5 based development -- and start latter from former. I'll
try to run the regression tests later today or tomorrow to see if I can
reproduce the problem.
Comment 5 Igor Fedorenko CLA 2004-07-05 09:24:40 EDT
FieldReference#getConstantFor cannot handle bindings to final members of
parametrized classes. At around line 352 it assumes that all
binding.declaringClass are instanced of SourceTypeBinding which is not the case
for parametrized types because ParameterizedTypeBinding is not subclass of
SourceTypeBinding. Here is a slightly modified version of my original example
that demostrates the problem (the only difference from original is "final"
qualifier of member "o").

==================================
package test.cheetah;
public class G<E> {
    protected final Object o;
}
==================================
package test.cheetah;
public class NG extends G {
    public boolean test() {
        return o == null;
    }
}
==================================


PS: am I right that a field has to be both final and static to be a constant?
Why can't you use "!binding.isFinal() || !binding.isStatic()" condition instead
of "!binding.isFinal()" at line 334?
Comment 6 Philipe Mulet CLA 2004-07-05 12:57:10 EDT
Constant fields do not need to be static.

I had indeed missed handling the final scenario.
Added support and regression test GenericTypeTest#test224.