1 /*******************************************************************************
2 * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v0.5
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v05.html
9 * IBM Corporation - initial API and implementation
10 ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.ast;
13 import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
14 import net.sourceforge.phpdt.internal.compiler.codegen.CodeStream;
15 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
16 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
17 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
18 import net.sourceforge.phpdt.internal.compiler.lookup.InvocationSite;
19 import net.sourceforge.phpdt.internal.compiler.lookup.LocalTypeBinding;
20 import net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding;
21 import net.sourceforge.phpdt.internal.compiler.lookup.MethodScope;
22 import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
23 import net.sourceforge.phpdt.internal.compiler.lookup.SourceTypeBinding;
24 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
25 import net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding;
27 public class ExplicitConstructorCall
29 implements InvocationSite {
31 public Expression[] arguments;
32 public Expression qualification;
33 public MethodBinding binding;
35 public int accessMode;
37 public final static int ImplicitSuper = 1;
38 public final static int Super = 2;
39 public final static int This = 3;
41 public VariableBinding[][] implicitArguments;
42 boolean discardEnclosingInstance;
44 MethodBinding syntheticAccessor;
46 public ExplicitConstructorCall(int accessMode) {
47 this.accessMode = accessMode;
50 public FlowInfo analyseCode(
51 BlockScope currentScope,
52 FlowContext flowContext,
55 // must verify that exceptions potentially thrown by this expression are caught in the method.
58 ((MethodScope) currentScope).isConstructorCall = true;
60 // process enclosing instance
61 if (qualification != null) {
64 .analyseCode(currentScope, flowContext, flowInfo)
65 .unconditionalInits();
68 if (arguments != null) {
69 for (int i = 0, max = arguments.length; i < max; i++) {
72 .analyseCode(currentScope, flowContext, flowInfo)
73 .unconditionalInits();
77 ReferenceBinding[] thrownExceptions;
78 if ((thrownExceptions = binding.thrownExceptions) != NoExceptions) {
80 flowContext.checkExceptionHandlers(
82 (accessMode == ImplicitSuper)
83 ? (AstNode) currentScope.methodScope().referenceContext
88 manageEnclosingInstanceAccessIfNecessary(currentScope);
89 manageSyntheticAccessIfNecessary(currentScope);
92 ((MethodScope) currentScope).isConstructorCall = false;
97 * Constructor call code generation
99 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
100 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
102 public void generateCode(BlockScope currentScope, CodeStream codeStream) {
104 if ((bits & IsReachableMASK) == 0) {
108 ((MethodScope) currentScope).isConstructorCall = true;
110 int pc = codeStream.position;
111 codeStream.aload_0();
113 // handling innerclass constructor invocation
114 ReferenceBinding targetType;
115 if ((targetType = binding.declaringClass).isNestedType()) {
116 codeStream.generateSyntheticArgumentValues(
119 discardEnclosingInstance ? null : qualification,
123 if (arguments != null) {
124 for (int i = 0, max = arguments.length; i < max; i++) {
125 arguments[i].generateCode(currentScope, codeStream, true);
128 if (syntheticAccessor != null) {
129 // synthetic accessor got some extra arguments appended to its signature, which need values
131 max = syntheticAccessor.parameters.length - binding.parameters.length;
134 codeStream.aconst_null();
136 codeStream.invokespecial(syntheticAccessor);
138 codeStream.invokespecial(binding);
140 codeStream.recordPositionsFrom(pc, this.sourceStart);
142 ((MethodScope) currentScope).isConstructorCall = false;
146 public boolean isImplicitSuper() {
147 //return true if I'm of these compiler added statement super();
149 return (accessMode == ImplicitSuper);
152 public boolean isSuperAccess() {
154 return accessMode != This;
157 public boolean isTypeAccess() {
162 /* Inner emulation consists in either recording a dependency
163 * link only, or performing one level of propagation.
165 * Dependency mechanism is used whenever dealing with source target
166 * types, since by the time we reach them, we might not yet know their
169 void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
170 ReferenceBinding superType;
172 // perform some emulation work in case there is some and we are inside a local type only
173 if ((superType = binding.declaringClass).isNestedType()
174 && currentScope.enclosingSourceType().isLocalType()) {
176 if (superType.isLocalType()) {
177 ((LocalTypeBinding) superType).addInnerEmulationDependent(
179 qualification != null,
181 // request direct access
183 // locally propagate, since we already now the desired shape for sure
184 currentScope.propagateInnerEmulation(superType, qualification != null, true);
185 // request direct access
191 public void manageSyntheticAccessIfNecessary(BlockScope currentScope) {
193 // perform some emulation work in case there is some and we are inside a local type only
194 if (binding.isPrivate() && (accessMode != This)) {
199 .isPrivateConstructorAccessChangingVisibility) {
200 binding.tagForClearingPrivateModifier();
201 // constructor will not be dumped as private, no emulation required thus
204 ((SourceTypeBinding) binding.declaringClass).addSyntheticMethod(binding);
205 currentScope.problemReporter().needToEmulateMethodAccess(binding, this);
210 public void resolve(BlockScope scope) {
211 // the return type should be void for a constructor.
212 // the test is made into getConstructor
214 // mark the fact that we are in a constructor call.....
215 // unmark at all returns
217 ((MethodScope) scope).isConstructorCall = true;
218 ReferenceBinding receiverType = scope.enclosingSourceType();
219 if (accessMode != This)
220 receiverType = receiverType.superclass();
222 if (receiverType == null) {
226 // qualification should be from the type of the enclosingType
227 if (qualification != null) {
228 if (accessMode != Super) {
229 scope.problemReporter().unnecessaryEnclosingInstanceSpecification(
233 ReferenceBinding enclosingType = receiverType.enclosingType();
234 if (enclosingType == null) {
235 scope.problemReporter().unnecessaryEnclosingInstanceSpecification(
238 discardEnclosingInstance = true;
240 TypeBinding qTb = qualification.resolveTypeExpecting(scope, enclosingType);
241 qualification.implicitWidening(qTb, qTb);
245 // arguments buffering for the method lookup
246 TypeBinding[] argTypes = NoParameters;
247 if (arguments != null) {
248 boolean argHasError = false; // typeChecks all arguments
249 int length = arguments.length;
250 argTypes = new TypeBinding[length];
251 for (int i = 0; i < length; i++)
252 if ((argTypes[i] = arguments[i].resolveType(scope)) == null)
257 if ((binding = scope.getConstructor(receiverType, argTypes, this))
259 if (isMethodUseDeprecated(binding, scope))
260 scope.problemReporter().deprecatedMethod(binding, this);
262 // see for user-implicit widening conversion
263 if (arguments != null) {
264 int length = arguments.length;
265 TypeBinding[] paramTypes = binding.parameters;
266 for (int i = 0; i < length; i++)
267 arguments[i].implicitWidening(paramTypes[i], argTypes[i]);
270 if (binding.declaringClass == null)
271 binding.declaringClass = receiverType;
272 scope.problemReporter().invalidConstructor(this, binding);
275 ((MethodScope) scope).isConstructorCall = false;
279 public void setActualReceiverType(ReferenceBinding receiverType) {
283 public void setDepth(int depth) {
287 public void setFieldIndex(int depth) {
291 public String toString(int tab) {
293 String s = tabString(tab);
294 if (qualification != null)
295 s = s + qualification.toStringExpression() + "."; //$NON-NLS-1$
296 if (accessMode == This) {
297 s = s + "this("; //$NON-NLS-1$
299 s = s + "super("; //$NON-NLS-1$
301 if (arguments != null)
302 for (int i = 0; i < arguments.length; i++) {
303 s = s + arguments[i].toStringExpression();
304 if (i != arguments.length - 1)
305 s = s + ", "; //$NON-NLS-1$
307 s = s + ")"; //$NON-NLS-1$
311 public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
313 if (visitor.visit(this, scope)) {
314 if (qualification != null) {
315 qualification.traverse(visitor, scope);
317 if (arguments != null) {
318 int argumentLength = arguments.length;
319 for (int i = 0; i < argumentLength; i++)
320 arguments[i].traverse(visitor, scope);
323 visitor.endVisit(this, scope);